Redis对象——有序集合(ZSet)
有序集合类型 (Sorted Set或ZSet) 相比于集合类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值。有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。

一、内部实现
有序集合是由 ziplist (压缩列表) 或 skiplist (跳跃表) 组成的。
当数据比较少时,有序集合使用的是 ziplist 存储的,有序集合使用 ziplist 格式存储必须满足以下两个条件:
- 有序集合保存的元素个数要小于 128 个;
- 有序集合保存的所有元素成员的长度都必须小于 64 字节。
如果不能满足以上两个条件中的任意一个,有序集合将会使用 skiplist 结构进行存储。
有关ziplist 和skiplist 这两种redis底层数据结构的具体实现可以参考我的另外两篇文章。
二、常用命令
Redis列表对象常用命令如下表(点击命令可查看命令详细说明)。
| 命令 | 说明 | 时间复杂度 |
|---|---|---|
| BZPOPMAX key [key ...] timeout | 从一个或多个排序集中删除并返回得分最高的成员,或阻塞,直到其中一个可用为止 | O(log(N)) |
| BZPOPMIN key [key ...] timeout | 从一个或多个排序集中删除并返回得分最低的成员,或阻塞,直到其中一个可用为止 | O(log(N)) |
| ZADD key [NXXX] [CH] [INCR] score member [score member ...] | 添加到有序set的一个或多个成员,或更新的分数,如果它已经存在 | O(log(N)) |
| ZCARD key | 获取一个排序的集合中的成员数量 | O(1) |
| ZCOUNT key min max | 返回分数范围内的成员数量 | O(log(N)) |
| ZINCRBY key increment member | 增量的一名成员在排序设置的评分 | O(log(N)) |
| ZINTERSTORE | 相交多个排序集,导致排序的设置存储在一个新的关键 | O(NK)+O(Mlog(M)) |
| ZLEXCOUNT key min max | 返回成员之间的成员数量 | O(log(N)) |
| ZPOPMAX key [count] | 删除并返回排序集中得分最高的成员 | O(log(N)*M) |
| ZPOPMIN key [count] | 删除并返回排序集中得分最低的成员 | O(log(N)*M) |
| ZRANGE key start stop [WITHSCORES] | 根据指定的index返回,返回sorted set的成员列表 | O(log(N)+M) |
| ZRANGEBYLEX key min max [LIMIT offset count] | 返回指定成员区间内的成员,按字典正序排列, 分数必须相同。 | O(log(N)+M) |
| ZREVRANGEBYLEX key max min [LIMIT offset count] | 返回指定成员区间内的成员,按字典倒序排列, 分数必须相同 | O(log(N)+M) |
| ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] | 返回有序集合中指定分数区间内的成员,分数由低到高排序。 | O(log(N)+M) |
| ZRANK key member | 确定在排序集合成员的索引 | O(log(N)) |
| ZREM key member [member ...] | 从排序的集合中删除一个或多个成员 | O(M*log(N)) |
| ZREMRANGEBYLEX key min max | 删除名称按字典由低到高排序成员之间所有成员。 | O(log(N)+M) |
| ZREMRANGEBYRANK key start stop | 在排序设置的所有成员在给定的索引中删除 | O(log(N)+M) |
| ZREMRANGEBYSCORE key min max | 删除一个排序的设置在给定的分数所有成员 | O(log(N)+M) |
| ZREVRANGE key start stop [WITHSCORES] | 在排序的设置返回的成员范围,通过索引,下令从分数高到低 | O(log(N)+M) |
| ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] | 返回有序集合中指定分数区间内的成员,分数由高到低排序。 | O(log(N)+M) |
| ZREVRANK key member | 确定指数在排序集的成员,下令从分数高到低 | O(log(N)) |
| ZSCORE key member | 获取成员在排序设置相关的比分 | O(1) |
| ZUNIONSTORE | 添加多个排序集和导致排序的设置存储在一个新的关键 | O(N)+O(M log(M)) |
| ZSCAN key cursor [MATCH pattern] [COUNT count] | 迭代sorted sets里面的元素 | O(1) |
三、使用场景
3.1 排行榜系统
有序集合比较典型的使用场景就是排行榜系统。例如学生成绩的排名。某视频(博客等)网站的用户点赞、播放排名、电商系统中商品的销量排名等。我们以博客点赞为例。
- 添加用户赞数
例如小编Tom发表了一篇博文,并且获得了10个赞。
zadd user:ranking arcticle1 10
- 取消用户赞数
这个时候有一个读者又觉得Tom写的不好,又取消了赞,此时需要将文章的赞数从榜单中减去1,可以使用zincrby。
zincrby user:ranking arcticle1 -1
- 查看某篇文章的赞数
ZSCORE user:ranking arcticle1
- 展示获取赞数最多的十篇文章
此功能使用zrevrange命令实现:
zrevrangebyrank user:ranking 0 9
3.2 电话号码(姓名)排序
使用有序集合的ZRANGEBYLEX(点击可查看该命令详细说明)或ZREVRANGEBYLEX可以帮助我们实现电话号码或姓名的排序,我们以ZRANGEBYLEX为例
注意:不要在分数不一致的SortSet集合中去使用 ZRANGEBYLEX和 ZREVRANGEBYLEX 指令,因为获取的结果会不准确。
- 电话号码排序
我们可以将电话号码存储到SortSet中,然后根据需要来获取号段:
redis> zadd phone 0 13100111100 0 13110114300 0 13132110901
(integer) 3
redis> zadd phone 0 13200111100 0 13210414300 0 13252110901
(integer) 3
redis> zadd phone 0 13300111100 0 13310414300 0 13352110901
(integer) 3
获取所有号码:
redis> ZRANGEBYLEX phone - +
1) "13100111100"
2) "13110114300"
3) "13132110901"
4) "13200111100"
5) "13210414300"
6) "13252110901"
7) "13300111100"
8) "13310414300"
9) "13352110901"
获取132号段:
redis> ZRANGEBYLEX phone [132 (133
1) "13200111100"
2) "13210414300"
3) "13252110901"
获取132、133号段:
redis> ZRANGEBYLEX phone [132 (134
1) "13200111100"
2) "13210414300"
3) "13252110901"
4) "13300111100"
5) "13310414300"
6) "13352110901"
- 姓名排序
将名称存储到SortSet中:
redis> zadd names 0 Toumas 0 Jake 0 Bluetuo 0 Gaodeng 0 Aimini 0 Aidehua
(integer) 6
获取所有人的名字:
redis> ZRANGEBYLEX names - +
1) "Aidehua"
2) "Aimini"
3) "Bluetuo"
4) "Gaodeng"
5) "Jake"
6) "Toumas"
获取名字中大写字母A开头的所有人:
redis> ZRANGEBYLEX names [A (B
1) "Aidehua"
2) "Aimini"
获取名字中大写字母C到Z的所有人:
redis> ZRANGEBYLEX names [C [Z
1) "Gaodeng"
2) "Jake"
3) "Toumas"
小结
本篇文章我们总结了Redis 有序集合对象的内部实现、常用命令以及常用的一些场景,有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能,合理的利用有序集合,能帮助我们在实际开发中解决很多问题。那么大家在项目中对Redis有序集合对象的使用都有哪些场景呢,欢迎在评论区给我留言和分享,我会第一时间反馈!我们共同学习与进步!
参考
《Redis设计与实现》
《Redis开发与运维》
《Redis官方文档》
-----END-----
Redis对象——有序集合(ZSet)的更多相关文章
- php使用redis的有序集合zset实现延迟队列
延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息. 延迟队列的应用场景: 1.新用户注册,10分钟后发送邮件或站内信. 2.用户下单后,30分钟未支付,订单自动作废. 我 ...
- 聊聊Mysql索引和redis跳表 ---redis的有序集合zset数据结构底层采用了跳表原理 时间复杂度O(logn)(阿里)
redis使用跳表不用B+数的原因是:redis是内存数据库,而B+树纯粹是为了mysql这种IO数据库准备的.B+树的每个节点的数量都是一个mysql分区页的大小(阿里面试) 还有个几个姊妹篇:介绍 ...
- redis的有序集合ZSET(stored set)
相关命令 1.ZADD ZADD key-name score member [score member……] 将带有给定分值的成员添加到有序集合里 2.ZREM ZREM key-name mem ...
- redis 有序集合(zset)函数
redis 有序集合(zset)函数 zAdd 命令/方法/函数 Adds the specified member with a given score to the sorted set stor ...
- 9、Redis五大数据类型---有序集合Zset(sorted set)
一.简介 zset与set异同 相同之处: 都是没有重复元素的字符串集合 不同之处: 有序集合zset的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排 ...
- [PHP] PHP多个进程配合redis的有序集合实现大文件去重
1.对一个大文件比如我的文件为 -rw-r--r-- 1 ubuntu ubuntu 9.1G Mar 1 17:53 2018-12-awk-uniq.txt 2.使用split命令切割成10 ...
- Redis 操作有序集合数据
Redis 操作有序集合数据: > zadd names "Tom" // zadd 用于往有序集合中添加元素,其中 1 在 Redis 中称为 score(分数),用来进行 ...
- python 操作redis之——有序集合(sorted set) (七)
#coding:utf8 import redis r =redis.Redis(host=") 1.Zadd 命令用于将一个或多个成员元素及其分数值加入到有序集当中.如果某个成员已经是有序 ...
- redis有序集合-zset
概念:它是在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动按新的值调整顺序.可以理解为有两列的mysql表,一列存储value,一列存储顺序,操作中 ...
随机推荐
- 44. 更改oracle字符集编码american_america.zh16gbk 改为 SIMPLIFIED CHINESE_CHINA.ZHS16GBK
注册表NLS_LANG值改为SIMPLIFIED CHINESE_CHINA.ZHS16GBK
- 大数据安装之Kafka(用于实时处理的消息队列)
一.安装部署kafka 1.集群规划 hadoop102 hadoop103 hado ...
- 查看oracle是否锁表以及解决方法
Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作,那么这些操作是怎么实现的呢?本文我们主要就介绍一下这部分内容.(1)锁表查询的代码有以下的形式: select count ...
- WebStorm添加Angular2服务启动的脚本命令
注意:选择的start在package.json可以修改. 例如添加一个run命令:
- Windows平台安装Beautiful Soup
Windows平台安装Beautiful Soup 2013-04-01 09:31:23| 分类: Python|举报|字号 订阅 Beautiful Soup是一个Python的一个库, ...
- Building Applications with Force.com and VisualForce(Dev401)( 八):Designing Applications for Multiple Users: Controling Access to Records.
Module Objectives1.List feature that affect access to data at the record level.2.List the organizati ...
- Vue路由配置history模式
我的博客: https://github.com/Daotin/fe-notes/issues vue需要node.js吗? 你可以用 script 标签的形式引入vue.min.js 这样的,不需要 ...
- coding++:TimeUnit 使用
TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段 主要作用 时间颗粒度转换 延时 常用的颗粒度 TimeUnit.DAYS //天 TimeUnit. ...
- [poj1797]Heavy Transportation<最大生成树prim&kruskal>
题目链接:http://poj.org/problem?id=1797 题意:给定n个点,m条边,每条边连接两点切有权值.求点1到点n的路径的上的最小边的值最大... 翻别人博客找到的题,方法挺多的, ...
- python ——钟表
1.表盘 from turtle import * from datetime import * def Skip(step):#表盘不连续地画图 penup() forward(step) pend ...