redis: sorted set数据类型与操作
2011-11-28 18:53
435 查看
redis支持有序集合,即sorted sets数据类型。基本格式为:
key --> member -- score
| --> member -- score
sorted set类型的实现采用了两个数据结构:hash table 和 skip list(跳跃表),其中hash table是具体使用redis中的dict来实现的,主要是为了保证查询效率为O(1) ,而skip list(跳跃表)主要是保证元素有序并能够保证INSERT和REMOVE操作是O(logn)的复杂度。
sorted set的基本操作详见:http://redis.readthedocs.org/en/2.4/sorted_set.html
利用redis c++接口,验证zset的基本操作:
PS:
redis c++接口在实现zset操作时,有两个小bug:
1. void recv_int_ok_reply_(int socket)
原来实现,当recv_int_reply_(socket) != 1时,就认为有错误,从而抛出异常:throw protocol_error("expecting int reply of 1");
但实际上,如zadd操作:
如果某个member已经是有序集的成员,那么更新这个member的score值,并通过重新插入这个member元素,来保证该member在正确的位置上,并返回0;
add成功返回1;如果key不存在,则创建一个空的有序集并执行zadd操作;当key存在但不是有序集类型时,返回一个错误。
修改:
2. void zrangebyscore(const string_type & key, double min, double max, string_score_vector & out, int_type offset = 0, int_type max_count = -1, int range_modification = 0)
调用,zrangebyscore_base(true, key, min, max, res, offset, max_count, range_modification);
第一个参数值等于true表明,需要返回score值。但是,zrangebyscore_base在实现时并未考虑这一参数。
修改:在zrangebyscore_base函数实现时,加上
key --> member -- score
| --> member -- score
sorted set类型的实现采用了两个数据结构:hash table 和 skip list(跳跃表),其中hash table是具体使用redis中的dict来实现的,主要是为了保证查询效率为O(1) ,而skip list(跳跃表)主要是保证元素有序并能够保证INSERT和REMOVE操作是O(logn)的复杂度。
sorted set的基本操作详见:http://redis.readthedocs.org/en/2.4/sorted_set.html
利用redis c++接口,验证zset的基本操作:
#include "redisclient.h" #include "tests/functions.h" #include <iostream> #include <boost/date_time.hpp> #define OUT(x) std::cout<<#x<<" = "<<x<<std::endl; boost::shared_ptr<redis::client> init_non_cluster_client(); void output_set(redis::client::string_set & sset); void output_sort_set(redis::client & c, std::string & key); void test_sorted_set(redis::client & c); int main(int argv, char* argc[]) { boost::shared_ptr<redis::client> shared_c; shared_c = init_non_cluster_client(); redis::client& c = *shared_c; test_sorted_set(c); return 0; } void test_sorted_set(redis::client & c) { test("test sorted set:"); std::string key = "page_rank"; test("zadd"); { c.zadd(key, 10, "taobao.com"); c.zadd(key, 9, "tmall.com"); c.zadd(key, make_pair("tmall.com", 11.1) ); output_sort_set(c, key); } test("zrem"); { c.zrem(key, "taobao.com"); output_sort_set(c, key); } test("zcount"); { OUT(c.zcount(key, 0, 5)); c.zadd(key, 3.6, "etao.com"); OUT(c.zcount(key, 0, 5)); } test("zincrby"); { c.zincrby(key,"etao.com", 3); c.zincrby(key,"koubei.com", 5); output_sort_set(c, key); } test("zrevrange"); { redis::client::string_vector out; c.zrevrange(key, 0, -1, out); for(size_t i=0; i<out.size(); ++i) { OUT(out[i]); } } test("zrangebyscore"); { redis::client::string_score_vector out; c.zrangebyscore(key, 0, 20, out, 0, 2); for(size_t i=0; i<out.size(); i++) { OUT(out[i].first); OUT(out[i].second); } } test("zrank & zrevrank"); { OUT(c.zrank(key, "etao.com")); OUT(c.zrevrank(key, "etao.com")); } test("zremrangebyrank & zremrangebyscore"); { c.zremrangebyrank(key, 0, 0); c.zremrangebyscore(key, 0, 10); output_sort_set(c, key); } test("zinterstore & zunionstore"); { c.zadd("website", 10, "taobao.com"); c.zadd("website", 8, "google.com"); c.zadd("website", 0, "baidu.com"); c.zadd("website", 7, "tmall.com"); redis::client::string_vector keys; keys.push_back(key); keys.push_back("website"); std::string sinter("inter"); std::string sunion("union"); c.zinterstore(sinter, keys); c.zunionstore(sunion, keys); std::cout<<"inter :"<<std::endl; output_sort_set(c, sinter); std::cout<<"union :"<<std::endl; output_sort_set(c, sunion); } } void output_sort_set(redis::client & c, std::string & key) { OUT( c.zcard(key) ); redis::client::string_vector out; c.zrange(key, 0, -1, out); for(size_t i=0; i<out.size(); ++i) { OUT(out[i]); OUT( c.zscore(key, out[i]) ); } }
PS:
redis c++接口在实现zset操作时,有两个小bug:
1. void recv_int_ok_reply_(int socket)
原来实现,当recv_int_reply_(socket) != 1时,就认为有错误,从而抛出异常:throw protocol_error("expecting int reply of 1");
但实际上,如zadd操作:
如果某个member已经是有序集的成员,那么更新这个member的score值,并通过重新插入这个member元素,来保证该member在正确的位置上,并返回0;
add成功返回1;如果key不存在,则创建一个空的有序集并执行zadd操作;当key存在但不是有序集类型时,返回一个错误。
修改:
void recv_int_ok_reply_(int socket) { if (recv_int_reply_(socket) < 0) throw protocol_error("expecting int reply of <0"); }
2. void zrangebyscore(const string_type & key, double min, double max, string_score_vector & out, int_type offset = 0, int_type max_count = -1, int range_modification = 0)
调用,zrangebyscore_base(true, key, min, max, res, offset, max_count, range_modification);
第一个参数值等于true表明,需要返回score值。但是,zrangebyscore_base在实现时并未考虑这一参数。
修改:在zrangebyscore_base函数实现时,加上
if(withscores) { m << "WITHSCORES"; }
相关文章推荐
- Redis----sorted set数据类型操作
- Redis数据类型操作(五) —— Sorted Set
- redis 学习手册之有序集合数据类型sorted-sets操作
- Redis数据类型之SORTEDSET类型
- redis学习篇(五)-----set类型和sorted set类型及相关操作
- 5.Redis学习-set数据类型操作
- Redis数据类型操作(四) —— Set
- Redis数据类型--SortedSet(有序集合)
- Redis初探06——Redis的有序集合sorted set类型及操作
- (六)redis常用数据类型 SortedSet
- Redis---set数据类型操作
- Redis详解:sorted sets数据类型及操作
- 跟我学REDIS-REDIS(五)----常用数据类型之SortedSet
- Redis和nosql简介,api调用;Redis数据功能(String类型的数据处理);List数据结构(及Java调用处理);Hash数据结构;Set数据结构功能;sortedSet(有序集合)数
- redis数据类型[string 、list 、 set 、sorted set 、hash]
- 跟我学Redis(8)—sorted set类型及操作
- redis安装及数据类型简介(string、list、set、sorted_set、hash)
- Redis和nosql简介,api调用;Redis数据功能(String类型的数据处理);List数据结构(及Java调用处理);Hash数据结构;Set数据结构功能;sortedSet(有序集合)数
- redis:set数据类型和操作
- NoSQL之Redis对set(集合)数据类型的操作之二