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。

时间: 2024-10-29 10:10:47

redis sorted sets操作学习笔记的相关文章

php 常用文件操作学习笔记

1.获取文件名:basename(); 2.获取文件所在的目录:dirname(); 3.pathinfo()获取文件信息,返回结果为一个array,包括路径.文件全名.文件名和扩展名.例如:  代码如下 复制代码 $file = '/com/netingcn/error.log'; print_r(pathinfo($file)); 结果为: Array(     [dirname] => /com/netingcn     [basename] => error.log     [exte

Python日期操作学习笔记_python

比如用 print ','.join(datelist) 就可以将datelist列表里面的所有项目并成一个字符串,当然这个表达式会在每一个项目中间插入一个逗号,这种方式比用循环的方式更简洁. 日期的操作必须使用time或datetime库 import time >>> s="2006-1-2" >>> time.strptime(s,"%Y-%m-%d) 这是将字符串格式的日期及时间转成日期对象 转义符对应意义如下 %a 本地简化星期名

php数组操作学习笔记

什么是数组? 数组是一个数据的集合,相当于一个容器,可以将数据按一定的规则存到这个容器中.相当于旅馆,旅馆内有很多房间,而房间按照一定的规则编号. 数组的构成:基本结构形式如下: $数组名 (键)= 值 数组名:是一个数组区别于另一个数组的方式,就像每个旅馆都有一个名字. 键(key):也成为指针.索引或者标识符.键代表某值在数组中存放的位置,相当于旅馆的门牌号,可以用不同方式命名.通过查询键可以找到相应的值. 值(value):值相当于房间内存放的东西. 赋值创建数组 在php中,创建数组有变

javascript 数组操作学习笔记

1.数组的创建  代码如下 复制代码 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长度 var arrayObj = new Array([element0[, element1[, ...[, elementN]]]]); 创建一个数组并赋值     要说明的是,虽然第二种方法创建数组指定了长度,但实际上所有情况下数组都是变长的,也就是说即使指定了长度为

dojo/dom-style样式操作学习笔记

基础总结 一个元素的样式信息由三个来源根据层叠规则确定.三个来源分别是: 由DOM元素style特性设置的内联样式 由style元素中嵌入的样式规则 由link元素引入的外部样式表 元素的样式 任何支持style特性的HTML元素在JavaScript中都有一个对应的style属性.这个style对象是CSSStyleDeclaration的实例,包含着通过HTML的style特性指定的所有样式信息,但不包含与外部样式表或嵌入样式表经层叠而来的样式.在style特性中指定的任何css属性都可以通

Redis学习笔记

1 安装 $ wget http://download.redis.io/releases/redis-3.0.7.tar.gz $ tar xzf redis-3.0.7.tar.gz $ cd redis-3.0.7 $ make 网页下载地址:http://www.redis.cn/download.html 2 启动服务端 $ src/redis-server 3 启动客户端 You can interact with Redis using the built-in client: $

redis 学习笔记(6)-cluster集群搭建

上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞sharding,现在方便多了,直接上cluster功能就行了,而且还支持节点动态添加.HA.节点增减后缓存重新分布(resharding). 下面是参考官方教程cluster-tutorial 在mac机上搭建cluster的过程: 一.下载最新版redis 编译 目前最新版是3.0.7,下载地址:http:

Perl学习笔记之文件操作

         这篇文章主要介绍了Perl学习笔记之文件操作,本文分别给出了打开文件.读取文件.写入文件代码实例,需要的朋友可以参考下              Perl对文件的操作,跟其它的语言类似,无非也就是打开,读与写的操作. 1. 打开文件 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #! c:/perl/bin/perl -w use utf8; use strict; use warnings;   my $filename = 'test.txt'

PHP图形操作之Jpgraph学习笔记_php技巧

本文实例讲述了PHP图形操作之Jpgraph学习笔记.分享给大家供大家参考,具体如下: 一.Jpgraph安装配置 下载Jpgraph安装包 解压后放置磁盘中,(最好是放在和网页一起) 修改php.ini文件: 1.内存  memory_limit=X,至少为32M 2.执行时间  max_execution_time=X,对于复杂的图片加载时需要较多的时间,根据图片的复杂度做相应的修改 3.缓存  output_buffering  注释掉缓存,便于调试 二.使用Jpgraph创建图形的基本步