[Redis][Zset]详细讲解
[Redis][Zset]详细讲解
·
目录
0.前言
-
它保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关联,这使得有序集合中的元素是可以维护有序性的,但这个有序不是⽤下标作为排序依据⽽是⽤这个分数
- 注意:
zset
内部是按照升序方式来排列的- 如果
score
相同,则按照元素自身字符串的字典序来排列
- 注意:
-
有序集合提供了获取指定分数和元素范围查找、计算成员排名等功能,合理地利⽤有序集合,可 以帮助在实际开发中解决很多问题
- 对于
ZSET
来说,既可以通过member
找到对应的score
,也可以通过score
找到匹配的member
- 对于
-
有序集合中的元素是不能重复的,但分数允许重复
1.常见命令
1.ZADD
- 功能:添加或者更新指定的元素以及关联的分数到
zset
中,分数应该符合double
类型,+inf/-inf
作为正负极限也是合法的 - 语法:
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member ...]
- 相关选项:
XX
:仅仅用于更新已经存在的元素,不会添加新元素NX
:仅用于添加新元素,不会更新已经存在的元素LT
:新score
小于当前score
,则更新GT
:新score
大于当前score
,则更新CH
:默认情况下,ZADD
返回的是本次添加的元素个数,但指定这个选项之后,就会还包含本次更新的元素的个数INCR
:此时命令类似ZINCRBY
的效果,将元素的分数加上指定的分数。此时只能指定一个元素和分数
- 返回值:本次添加成功的元素个数
- 时间复杂度: O ( l o g ( N ) ) O(log(N)) O(log(N))
2.ZCARD
- 功能:获取一个
zset
的计数(cardinality),即zset
中的元素个数 - 语法:
ZCARD key
- 返回值:
zset
内的元素个数 - 时间复杂度: O ( 1 ) O(1) O(1)
3.ZCOUNT
- 功能:返回分数在
min
和max
之间的元素个数- 默认情况下,
min
和max
都是包含的,可以通过(
排除 -> 表示开区间 - 左右区间都只能用
(
排除,而不是左区间用(
,右区间用)
- 默认情况下,
- 语法:
ZCOUNT key min max
- 返回值:满足条件的元素列表个数
- 时间复杂度: O ( l o g ( N ) ) O(log(N)) O(log(N))
4.ZRANGE
- 功能:返回指定区间⾥的元素,分数按照升序,带上
WITHSCORES
可以把分数也返回 - 语法:
ZRANGE key start stop [WITHSCORES]
- 返回值:区间内的元素列表
- 时间复杂度: O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)
5.ZREVRANGE
- 功能:返回指定区间⾥的元素,分数按照降序,带上
WITHSCORES
可以把分数也返回- 注意:这个命令可能在6.2.0之后废弃,并且功能合并到
ZRANGE
中
- 注意:这个命令可能在6.2.0之后废弃,并且功能合并到
- 语法:
ZREVRANGE key start stop [WITHSCORES]
- 返回值:区间内的元素列表
- 时间复杂度: O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)
6.ZRANGEBYSCORE
- 功能:返回分数在
min
和max
之间的元素,默认情况下,min
和max
都是包含的,可以通过(
排除- 注意:这个命令可能在6.2.0之后废弃,并且功能合并到
ZRANGE
中
- 注意:这个命令可能在6.2.0之后废弃,并且功能合并到
- 语法:
ZRANGEBYSCORE key min max [WITHSCORES]
- 返回值:区间内的元素列表
- 时间复杂度: O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)
7.ZPOPMAX
- 功能:删除并返回分数最高的
count
个元素 - 语法:
ZPOPMAX key [count]
- 返回值:分数和元素列表
- 时间复杂度: O ( l o g ( N ) ∗ M ) O(log(N) * M) O(log(N)∗M)
8.BZPOPMAX
- 功能:
ZPOPMAX
的阻塞版本 - 语法:
BZPOPMAX key [key ...] timeout
timeout
:单位为秒,支持浮点数
- 返回值:元素列表
- 时间复杂度: O ( l o g ( N ) ) O(log(N)) O(log(N))
9.ZPOPMIN
- 功能:删除并返回分数最低的
count
个元素 - 语法:
ZPOPMIN key [count]
- 返回值:分数和元素列表
- 时间复杂度: O ( l o g ( N ) ∗ M ) O(log(N) * M) O(log(N)∗M)
10.BZPOPMIN
- 功能:
ZPOPMIN
的阻塞版本 - 语法:
BZPOPMIN key [key ...] timeout
- 返回值:元素列表
- 时间复杂度: O ( l o g ( N ) ) O(log(N)) O(log(N))
11.ZRANK
- 功能:返回指定元素的排名,升序
- 语法:
ZRANK key member
- 返回值:排名
- 时间复杂度: O ( l o g ( N ) ) O(log(N)) O(log(N))
12.ZREVRANK
- 功能:返回指定元素的排名,降序
- 语法:
ZREVRANK key member
- 返回值:排名
- 时间复杂度: O ( l o g ( N ) ) O(log(N)) O(log(N))
13.ZSCORE
- 功能:返回指定元素的分数
- 语法:
ZSCORE key member
- 返回值:分数
- 时间复杂度: O ( 1 ) O(1) O(1)
14.ZREM
- 功能:删除指定元素
- 语法:
ZREM key member [member ...]
- 返回值:本次操作删除的元素个数
- 时间复杂度: O ( l o g ( N ) ∗ M ) O(log(N) * M) O(log(N)∗M)
15.ZREMRANGEBYRANK
- 功能:按照排序,升序删除指定范围的元素,左闭右闭
- 语法:
ZREMRANGEBYRANK key start stop
- 返回值:本次操作删除的元素个数
- 时间复杂度: O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)
16.ZREMRANGEBYSCORE
- 功能:按照分数删除指定范围的元素,左闭右闭
- 语法:
ZREMRANGEBYSCORE key min max
- 返回值:本次操作删除的元素个数
- 时间复杂度: O ( l o g ( N ) + M ) O(log(N) + M) O(log(N)+M)
17.ZINCRBY
- 功能:为指定的元素的关联分数添加指定的分数值
- 语法:
ZINCRBY key increment member
- 返回值:增加后元素的分数
- 时间复杂度: O ( l o g ( N ) ) O(log(N)) O(log(N))
2.集合间操作
1.有序集合的交集操作
2.ZINTERSTORE
- 功能:求出给定有序集合中元素的交集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元 素对应的分数按照不同的聚合⽅式和权重得到新的分数
- 语法:
ZINTERSTORE dest numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE]
- 注意:
numkeys
必须准确填写,以便后面将参数准确解析
- 注意:
- 返回值:⽬标集合中的元素个数
- 时间复杂度: O ( N ∗ K ) + O ( M ∗ l o g ( M ) ) O(N*K)+O(M*log(M)) O(N∗K)+O(M∗log(M)),N是输⼊的有序集合中最⼩的有序集合的元素个数,K是输⼊了 ⼏个有序集合,M是最终结果的有序集合的元素个数
3.有序集合的并集操作
4.ZUNIONSTORE
- 功能:求出给定有序集合中元素的并集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元 素对应的分数按照不同的聚合⽅式和权重得到新的分数
- 语法:
ZUNIONSTORE dest numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE ]
- 返回值:目标集合中的元素个数
- 时间复杂度: O ( N ) + O ( M ∗ l o g ( M ) ) O(N)+O(M*log(M)) O(N)+O(M∗log(M)),N是输⼊的有序集合总的元素个数,M是最终结果的有序集合的元素个数
3.内部编码
1.ziplist(压缩链表)
- 当有序集合的元素个数⼩于
zset-max-ziplist-entries
配置(默认128个), 同时每个元素的值都⼩于zset-max-ziplist-value
配置(默认64字节)时,Redis会⽤ziplist
来作为有序集合的内部实现,ziplist
可以有效减少内存的使⽤
2.skiplist(跳表)
- 当
ziplist
条件不满⾜时,有序集合会使⽤skiplist
作为内部实现,因为此时ziplist
的操作效率会下降
4.使用场景
- 有序集合⽐较典型的使⽤场景就是排⾏榜系统
- 例如:常⻅的⽹站上的热榜信息,榜单的维度可能是多⽅⾯的:按照时间、按照阅读量、按照点赞量
- 示例:凭借点赞数,维护每天的热榜
- 添加用户点赞数:
# ⽤⼾james发布了⼀篇⽂章,并获得3个赞,可以使⽤有序集合的zadd和zincrby功能 zadd user:ranking:2024-09-01 3 james # 之后如果再获得赞,可以使⽤zincrby zincrby user:ranking:2022-03-15 1 james
- 取消用户点赞数:
# 由于各种原因需要将⽤⼾删除,此时需要将⽤⼾从榜单中删除掉,可以使⽤zrem zrem user:ranking:2024-09-01 tom
- 展示获取赞数最多的10个用户:
zrevrangebyrank user:ranking:2024-09-01 0 9
- 展示用户信息以及用户分数:次功能将⽤⼾名作为键后缀,将⽤⼾信息保存在哈希类型中,⾄于⽤⼾的分数和排名可以使⽤
zscore
和zrank
来实现hgetall user:info:tom zscore user:ranking:2022-03-15 mike zrank user:ranking:2022-03-15 mike
- 添加用户点赞数:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献7条内容
所有评论(0)