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,一列存储顺序,操作中 ...
随机推荐
- java -封装一个类。(姓名、年龄、性别)
//定义一个类. public class Maopao1{ //创建私有的对象. private String name; private int age; private String sex; ...
- 基于Jquery WeUI的微信开发H5页面控件的经验总结(2)
在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...
- [剑指offer]6.从尾到头打印链表+18.删除链表节点
链表 6.从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 方法一 迭代 创建空列表res,将链表值head.val依次存进res,返回翻转后的res 代码 cl ...
- SVN分支合并指南
SVN分支合并主干具体操作步骤 1. 在装有svn插件的myeclipse中,在主干上选择需要合并的文件或文件夹, 右击--> team -->合并(merge) 2.选择合并类型--合并 ...
- Redis源码分析: String(SDS)容量调整分析
整体思路: 1 惰性缩容.不释放空间,留给到期释放等机制释放. 2 加倍扩容.在需要空间达1M之前按新空间两倍分配空间,否则按新空间大小+1M分配.注意,1M=1024*1024*Char.Char可 ...
- 滑动窗口-Moving Stones Until Consecutive II
2020-02-20 16:34:16 问题描述: 问题求解: public int[] numMovesStonesII(int[] stones) { int n = stones.length; ...
- [贪心,dp] 2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛 Fishing Master (Problem - 6709)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=6709 Fishing Master Time Limit: 2000/1000 MS (Java/Othe ...
- latex中文支持ubuntu
latex安装: sudo apt install texlive-full 中文字体安装: sudo apt-get install latex-cjk-all 字体包中包含bsmi,bk ...
- 用序列到序列和注意模型实现的:Translation with a Sequence to Sequence Network and Attention
In this project we will be teaching a neural network to translate from French to English. 最后效果: [KEY ...
- 【SQL SERVER】索引
在做开发过程中经常会接触数据库索引,不只是DBA才需要知道索引知识,了解索引可以让我们写出更高质量代码. 索引概述 聚集索引 非聚集索引 唯一索引 筛选索引 非聚集索引包含列 索引概述 索引的存在主要 ...