有道无术,术尚可求,有术无道,止于术。
本系列Redis 版本 7.2.5
源码地址:https://gitee.com/pearl-organization/study-redis-demo
文章目录
- 1. 概述
- 2. 常用命令
- 2.1 ZADD
- 2.2 ZCARD
- 2.3 ZSCORE
- 2.4 ZRANGE
- 2.5 ZREVRANGE
- 2.6 ZRANK
- 2.7 ZREM
- 2.8 ZPOPMIN
- 2.9 ZPOPMAX
- 2.10 ZINCRBY
- 2.11 集合运算
- 3. 应用场景
1. 概述
ZSet
是一种有序集合类型,可以存储不重复的元素,并且给每个元素赋予一个 double
类型的排序权重值(score
)。
2. 常用命令
ZSet
相关所有命令:
命名 | 描述 |
---|---|
BZMPOP | 按照指定的排序方式推出多个队列中指定数量的元素 |
BZPОPMAX | ZPOPMAX 的阻塞版本,作用相同,只是在目标集合中没有元素时会阻塞,timeout 参数指定了过期时间 (0 表示永不超时) |
BZPOPMIN | 与 ZPOPMAX 一样,只是返回 score 最小的 |
ZADD | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
ZCARD | 获取有序集合的成员数 |
ZCOUNT | 计算在有序集合中指定区间分数的成员数 |
ZDIFF | 返回集合之间的差集 |
ZDIFFSTORE | 返回集合之间的差集,并将结果存储在另一个新的有序集合中 |
ZINCRBY | 有序集合中对指定成员的分数加上增量 increment |
ZINTER | 用于计算多个有序集合的交集 |
ZINTERCARD | 用于计算多个有序集合的交集,并返回成员个数 |
ZINTERSTORE | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 |
ZLEXCOUNT | 计算有序集合中指定区间内成员的数量 |
ZMPOP | 弹出一个或多个成员 |
ZMSCORE | 从有序集合中获取多个成员的分数(score ) |
ZPOPMAX | 用于删除并返回集合中分数(score )最高的一个或多个元素。如果集合为空,则命令不执行任何操作 |
ZPOPMIN | 用于删除并返回集合中分数(score )最低的一个或多个元素。如果集合为空,则命令不执行任何操作 |
ZRANDMEMBER | 随机获取一个或多个元素 |
ZRANGE | 获取指定范围内的成员 |
ZRANGEBYLEX | 根据成员名称的字典顺序来返回有序集合中指定区间的成员。注意是基于成员名称的字典顺序,而不是分数(score )的大小 |
ZRANGEBYSCORE | 返回有序集中指定分数区间内的成员,分数从高到低排序 |
ZRANGESTORE | 绍 返回集合中指定排名范围内的成员,并将结果存储到指定key 中 |
ZRANK | 返回有序集合中指定成员的索引 |
ZREM | 移除有序集合中的一个或多个成员 |
ZREMRANGEBYLEX | 移除有序集合中给定的字典区间的所有成员 |
ZREMRANGEBYRANK | 移除有序集合中给定的排名区间的所有成员 |
ZREMRANGEBYSCORE | 移除有序集合中给定的分数区间的所有成员 |
ZREVRANGE | 返回有序集中指定区间内的成员,通过索引,分数从高到底 |
ZREVRANGEBYLEX | 根据字典范围返回成员,返回的成员顺序是反向的,即从高到低的字典顺序 |
ZREVRANGEBYSCORE | 返回指定分数范围内的成员,并按照分数从高到低进行排序 |
ZREVRANK | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
ZSCAN | 迭代有序集合中的元素(包括元素成员和元素分值) |
ZSCORE | 返回有序集中,成员的分数值 |
ZUNION | 计算一个或多个有序集的并集 |
ZUNIONSTORE | 计算一个或多个有序集的并集,并存储在新的 key 中 |
2.1 ZADD
ZADD
命令用于将一个或多个元素及其 score
值加入到有序集 key
中。
注意事项:
- 如果某个
member
已经是有序集的成员,那么更新这个member
的score
值,并通过重新插入这个member
元素,来保证该member
在正确的位置上。 - 如果有序集合
key
不存在,则创建一个空的有序集并执行ZADD
操作。 - 当
key
存在但不是有序集类型时,返回一个错误。 score
值可以是整数值或双精度浮点数,score
可为正也可以为负。- 获取一个成员当前的分数可以使用
ZSCORE
命令,也可以用它来验证成员是否存在。
基本语法:
ZADD key [NX|XX] [CH] [INCR] score member [score member …]
添加单个元素:
redis> ZADD page_rank 10 google.com
(integer) 1
添加多个元素:
redis> ZADD page_rank 9 baidu.com 8 redis.com.cn
(integer) 2
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "redis.com.cn"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
添加已存在元素,且 score
值不变:
redis> ZADD page_rank 10 google.com
(integer) 0
redis> ZRANGE page_rank 0 -1 WITHSCORES # 没有改变
1) "redis.com.cn"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
添加已存在元素,但是改变 score
值:
redis> ZADD page_rank 6 redis.com.cn
(integer) 0
redis> ZRANGE page_rank 0 -1 WITHSCORES # redis.com.cn 元素的 score 值被改变
1) "redis.com.cn"
2) "6"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
ZADD
命令支持参数,参数位于 key
名字和第一个 score
参数之间(GT
、LT
和 NX
三者互斥不能同时使用):
XX
: 仅更新存在的成员,不添加新成员。NX
:不更新存在的成员,只添加新成员。LT
: 更新新的分值比当前分值小的成员,不存在则新增。GT
: 更新新的分值比当前分值大的成员,不存在则新增。CH
:返回变更成员的数量。变更的成员是指新增成员 和score
值更新的成员,命令指明的和之前score
值相同的成员不计在内。 在通常情况下,`ZADD 返回值只计算新添加成员的数量。INCR
:ZADD
使用该参数与ZINCRBY
功能一样。一次只能操作一个score-element
对。
Redis
有序集合的分数使用双精度 64
位浮点数表示。在 Redis
所支持的平台上,称为 IEEE 754 floating point number
,它能包括的整数范围是-(2^53)
到 +(2^53)
。或者说是-9007199254740992
到 9007199254740992
。更大的整数在内部用指数形式表示,所以,如果为分数设置一个非常大的整数,你得到的是一个近似的十进制数。
有序集合按照分数以递增的方式进行排序。相同的成员(member
)只存在一次,有序集合不允许存在重复的成员。 分数可以通过 ZADD
命令进行更新或者也可以通过 ZINCRBY
命令递增来修改之前的值,相应的他们的排序位置也会随着分数变化而改变。
有序集合里面的成员是不能重复的都是唯一的,但是,不同成员间有可能有相同的分数。当多个成员有相同的分数时,他们将是按字典排序(ordered lexicographically
)(仍由分数作为第一排序条件,然后,相同分数的成员按照字典序排序)。
字典顺序排序用的是二进制,它比较的是字符串的字节数组。如果用户将所有元素设置相同分数(例如 0
),有序集合里面的所有元素将按照字典顺序进行排序,范围查询元素可以使用 ZRANGEBYLEX
命令(注:范围查询分数可以使用ZRANGEBYSCORE
命令)。
2.2 ZCARD
ZCARD
命令用于返回有序集的成员个数,当 key
不存在时,返回 0 。
基本语法:
ZCARD key
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZCARD myzset
(integer) 2
2.3 ZSCORE
ZSCORE
命令用于返回有序集 key
.中成员 member
的分数,返回值为字符串格式的双精度浮点数。如果有不存在的 member
,或者 key
不存在,返回 nil
。
基本语法:
ZSCORE key member
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZSCORE myzset "one"
"1"
2.4 ZRANGE
ZRANGE
命令返回有序集中指定区间内的成员,其中成员的按分数值递增(从小到大)来排序,具有相同分数值的成员按字典序排列。
注意事项:
- 如果你需要成员按值递减来排列,请使用
ZREVRANGE
命令。 - 下标参数
start
和stop
都以0
为底,也就是说,以0
表示有序集第一个成员,以1
表示有序集第二个成员,以此类推。 - 也可以使用负数下标,以
-1
表示最后一个成员,-2
表示倒数第二个成员,以此类推。 start
和stop
都是包含在内的区间,因此例如ZRANGE myzset 0 1
将会返回有序集合的第一个和第二个元素。- 超出范围的索引不会产生错误。 如果
start
参数的值大于有序集合中的最大索引,或者start > stop
,将会返回一个空列表。 如果stop
的值大于有序集合的末尾,会将其视为有序集合的最后一个元素。 - 可以传递
WITHSCORES
选项,以便将元素的分数与元素一起返回。这样返回的列表将包含value1,score1,...,valueN,scoreN
,而不是value1,...,valueN
。 客户端类库可以自由地返回更合适的数据类型(建议:具有值和得分的数组或元组)。
基本语法:
ZRANGE key start stop [WITHSCORES]
简单示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZRANGE myzset 0 -1
1) "one"
2) "two"
3) "three"
redis> ZRANGE myzset 2 3
1) "three"
redis> ZRANGE myzset -2 -1
1) "two"
2) "three"
WITHSCORES
示例:
redis> ZRANGE myzset 0 1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
2.5 ZREVRANGE
ZREVRANGE
命令返回有序集中,指定区间内的成员。其中成员的位置按 score
值递减(从高到低)来排列。除了成员排序相反外,其他方面和 ZRANGE
命令一样。
基本语法:
ZREVRANGE key start stop [WITHSCORES]
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREVRANGE myzset 0 -1
1) "three"
2) "two"
3) "one"
redis> ZREVRANGE myzset 2 3
1) "one"
redis> ZREVRANGE myzset -2 -1
1) "two"
2) "one"
2.6 ZRANK
ZRANK
命令返回有序集中成员的排名,其中有序集成员按 score
值从低到高排列。排名从 0
开始,也就是说,分值最低的成员排名为 0
。
基本语法:
ZRANK key member
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZRANK myzset "three"
(integer) 2
redis> ZRANK myzset "four"
(nil)
2.7 ZREM
ZREM
命令用于从有序集合中删除指定的成员,如果 member
不存在则被忽略。当 key
存在,但是不是有序集合类型时,返回类型错误。
基本语法:
ZREM key member [member ...]
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREM myzset "two"
(integer) 1
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "three"
4) "3"
2.8 ZPOPMIN
ZPOPMIN
删除并返回最多 count
个有序集合 key
中最低得分的成员。返回值为删除的元素和分数列表。
注意事项:
- 如未指定,
count
的默认值为1
。 - 指定一个大于有序集合的候选总数的
count
不会产生错误。 - 当返回多个元素时候,得分最低的元素将是第一个元素,然后是分数较高的元素。
基本语法:
ZPOPMIN key [count]
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZPOPMIN myzset
1) "one"
2) "1"
2.9 ZPOPMAX
ZPOPMAX
删除并返回最多 count
个有序集合 key
中的最高得分的成员。返回值为删除的元素和分数列表。
注意事项:
- 如未指定,
count
的默认值为1
。 - 指定一个大于有序集合的候选总数的
count
不会产生错误。 - 当返回多个元素时候,得分最高的元素将是第一个元素,然后是分数较低的元素。
基本语法:
ZPOPMAX key [count]
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZPOPMAX myzset
1) "three"
2) "3"
2.10 ZINCRBY
ZINCRBY
为有序集 key
的成员 member
的 score
值加上增量 increment
。返回值为以字符串形式表示的成员的新 score
值(双精度浮点数)。
注意事项:
- 当
key
不存在,或member
不是key
的成员时,ZINCRBY key increment member
等同于ZADD key increment member
。 - 当
key
不是有序集类型时,返回"ERR WRONGTYPE Operation against a key holding the wrong kind of value"
。 score
值可以是字符串形式表示的整数值或双精度浮点数。- 可以通过传递一个负数值
increment
,让score
减去相应的值,比如ZINCRBY key -2 member
,就是让member
的score
值减去2
。
基本语法:
ZINCRBY key increment member
示例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZINCRBY myzset 2 "one"
"3"
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "two"
2) "2"
3) "one"
4) "3"
2.11 集合运算
和 Set
一样,也支持集合运算:
- 交:
ZINTER
ZINTERCARD
ZINTERSTORE
- 并:
ZUNION
ZUNIONSTORE
- 差:
ZDIFF
ZDIFFSTORE
3. 应用场景
ZSet
在 Set
的基础上增加了分值排序,常用于排行榜场景,比如热搜、成绩排名等。
例如,添加搜索消息,并初始化访问值为 1
:
localhost:0>ZADD msg_rank 1 msg_1
"1"
localhost:0>ZADD msg_rank 1 msg_2
"1"
localhost:0>ZADD msg_rank 1 msg_3
"1"
用户点击消息时,增加访问次数:
"1"
localhost:0>ZINCRBY msg_rank 1 msg_2
"1"
localhost:0>ZINCRBY msg_rank 1 msg_3
"2"
localhost:0>ZINCRBY msg_rank 1 msg_3
"3"
显示热搜前十排行榜:
localhost:0>ZREVRANGE msg_rank 0 9 WITHSCORES
1) "msg_3"
2) "3"
3) "msg_2"
4) "1"
5) "msg_1"
6) "1"