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的基本操作:
#include "redisclient.h"
#include "tests/functions.h"
#include
#include
#define OUT(x) std::cout<<#x<<" = "< 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 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
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");
}
调用,zrangebyscore_base(true, key, min, max, res, offset, max_count, range_modification);
第一个参数值等于true表明,需要返回score值。但是,zrangebyscore_base在实现时并未考虑这一参数。
修改:在zrangebyscore_base函数实现时,加上
if(withscores) {
m << "WITHSCORES";
}