有序集合Zset
有序集合不能有重复元素,元素可以排序,和列表的索引下标不同,排序的依据是分数(Score),分数可以重复,提供获取指定分数和元素范围查询、计算成员排名等功能
数据结构 | 是否允许重复元素 | 是否有序 | 有序实现方式 | 应用场景 |
列表 | 是 | 是 | 索引下标 | 时间轴、消息队列等 |
集合 | 否 | 否 | 无 | 标签、社交等 |
有序集合 | 否 | 是 | 分数 | 排行榜系统、社交等 |
常用命令
集合内
添加成员:zadd key score member [score member …]
zdd有nx、xx、ch、incr四个选项(Redis3.2增加):
nx:member必须不存在,才可以设置成功,用于添加
xx:member必须存在,才能设置成功,用于更新
ch:返回此次操作后,有序集合元素和分数发生变化的个数
incr:对score做增加,相当于zincrbymingl
zadd的时间复杂度是O(log(n)),而sadd时间复杂度是O(1),提供了排序字段,也产生了代价
计算成员个数:zcard key
计算某个成员的分数:zscore key member
计算成员的排名:zrank key member 和zrevrank key member
zrank是从分数低到高返回成员的排名,zrevrank则反之
删除成员: zrem key member [member …]
增加成员的分数:zincrby key increment member
返回指定排名范围的成员: zrange key start end [withscores] 和 zrevrange key start end [withscores]
加上withscores会同时返回成员的分数
返回指定分数范围的成员:
zrangebyscore key min max [withscores] [limit offset count]
zrevrangebyscore key min max [withscores] [limit offset count]
withscores会同时返回成员的分数
limit offset count限制输出的起始位置和个数
min和max支持开区间(小括号)和闭区间(中括号),-inf和+inf分表表示无限小和无限大
返回指定分数范围成员个数:zcount key min max
删除指定排名内的升序元素:zremrangebyrank key start end
删除指定分数范围的成员:zremrangebyscore key min max
集合间
- 交集
zinterstore destination numkeys key [key…] [weights weight [weight …]] [aggregate sum|min|max]
destination:交集计算结果保存的键
numkeys:需要做交集计算键的个数
key[key …]:需要做交集计算的键
weights weight[weight …]:每个键的权重,默认为1,计算时,键中的每个member会将分数乘以权重,每个weight对应上面的每个key
aggregate sum|min|max:计算成员交集后,分值可以按照sum、min、max做汇总,默认为sum
- 并集
zunionstore destination numkeys key [key …] [weights weight [weight …]] [aggreagate sum|max|min]
有序集合的时间复杂度
内部编码
- ziplist:压缩列表,当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),且每个元素的值都小于zset-max-ziplist-value配置(默认64字节),Redis会使用ziplist作为有序集合的内部实现,可以有效减少内存的使用。
- skiplist:跳跃表,当ziplist条件不满足时,有序集合使用skiplist作为内部实现,因为此时ziplist的读写效率会下降
使用场景
有序集合比较典型的使用场景就是排行榜系统,可以按照不同维度进行维护,比如视频网站的榜单可以按照实际、播放数量、获得赞数。
如对于获取赞数这个维度,记录每天用户上传收盘的排行榜,主要包括以下四个功能
- 添加用户赞数
通过zadd和zincrby记录,mike上传视频获得3个赞,然后又获得了1个赞
zdd user:ranking:2020_03_30 3 mike
zincrby user:ranking:2020_03_30 1 mike
- 取消用户赞数
由于一些原因(如用户注销、作弊等)需要将用户删除,可以使用zrem命名。
zrem user:ranking:2020_03_30 mike
- 展示获取赞数最多的10个用户
zrevrangebyrank user:ranking:2020_03_30 0 9
- 展示用户分数
zscore user:ranking:2020_03_30 mike
zrank user:ranking:2020_03_30 mike