百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>数据库> redis sorted sets操作学习笔记
分享文章到:

redis sorted sets操作学习笔记

发布时间:01/15 来源: 浏览: 关键词:
本文章介绍redis sorted sets操作学习笔记,有需要了解的同学可参考。


sorted set是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加

修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解为有

两列的mysql表,一列存value,一列存顺序。操作中key理解为zset的名字。


和set一样sorted  set也是string类型元素的集合,不同的是每个元素都会关联一个double

类型的score。sorted set的实现是skip list和hash table的混合体。

当元素被添加到集合中时,一个元素到score的映射被添加到hash  table中,所以给定一个

元素获取score的开销是O(1),另一个score到元素的映射被添加到skip list,并按照score排

序,所以就可以有序的获取集合中的元素。添加,删除操作开销都是O(log(N))和skip list的

开销一致,redis 的skip list实现用的是双向链表,这样就可以逆序从尾部取元素。sorted set最

经常的使用方式应该是作为索引来使用.我们可以把要排序的字段作为score存储,对象的id

当元素存储.

下面讲一个使用 Sorted Sets 的例子

mysql中有一张表,假设名字为 summary_data吧,记录数为30M左右,
有一个字段first_path 为varchar(256),需要找到出现次数最多的10个first_path。

方法一 ) 直接sql语句

sql语句很好写:

 代码如下
SELECT first_path, COUNT(*) AS c FROM summary_data GROUP BY first_path ORDER BY c DESC LIMIT 10;

表上面是有索引的, 但是索引的长度为 KEY `first_path` (`first_path`(255)), 也许是这个原因导致了无法使用索引:
id: 1
select_type: SIMPLE
table: summary_data
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 28136948
Extra: Using temporary; Using filesort

这条sql运行了9分钟。

把first_path都导出来,生成文件 input/first_path, 每行一条记录,话说这个导出的过程真的很慢。

方法二 ) sort 与 uniq

sort  input/first_path | uniq -c |sort -nr | head -n 10
排好序的状态,就是分组的状态了。
uniq -c 用来统计每组的数量。
sort -nr 再对统计结果进行降序
一分半钟搞定。

方法三 ) redis的sorted set

用这种方法,只因为突然想到sorted set就是为此而生的嘛。

client libary 准备用 hiredis.

安装很简单: make && make install
可以看到库文件安装到了 /usr/local/lib/ 目录
头文件安装到了 /usr/local/include/hiredis/ 目录

需要把 /usr/local/lib/ 添加到 /etc/ld.so.conf
然后ldconfig

编译一下:

 代码如下

gcc -I /usr/local/include/hiredis -lhiredis ./example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <hiredis.h>
 
int main(int argc, char **argv) {
    unsigned int j;
    redisContext *c;
    redisReply *reply;
    const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1";
    int port = (argc > 2) ? atoi(argv[2]) : 6379;
 
    struct timeval timeout = { 1, 500000 }; // 1.5 seconds
    c = redisConnectWithTimeout(hostname, port, timeout);
    if (c == NULL || c->err) {
        if (c) {
            printf("Connection error: %sn", c->errstr);
            redisFree(c);
        } else {
            printf("Connection error: can't allocate redis contextn");
        }
        exit(1);
    }
 
        FILE * fp;
 
 
        fp = fopen(argv[3], "r");
        if (!fp) exit(1);
 
        char line[256];
 
        while(fgets(line, sizeof(line)-1, fp ) != NULL) {
                reply = redisCommand(c, "ZINCRBY myzset_firstpath  1 %s"        , line);
                freeReplyObject(reply);
        }
 
        fclose(fp);
 
        reply = redisCommand(c, "ZREVRANGEBYSCORE myzset_firstpath +inf -inf WITHSCORES LIMIT  0 10");
 
                if (reply->type == REDIS_REPLY_ARRAY) {
                        for (j = 0; j < reply->elements; j+=2) {
                                printf("%u) %s  %sn", (unsigned int)(j/2), reply->element[j]->str, reply->element[j+1]->str);
                        }
                }
 
 
        freeReplyObject(reply);
    /* Disconnects and frees the context */
    redisFree(c);
 
    return 0;
}

16分钟出结果, not good enough。

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有6人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板