Redis 的命令详解 - Sorted Set 篇
Sorted Set 命令详解
跟 SET 相关的命令一共有 25 种,这里只介绍常用的
ZADD : 添加成员
起始版本 : 1.2.0
时间复杂度 : O(log(N)),其中N是有序集合中的元素数。
向有序集合(sorted set)中,添加 分数/成员(score/member)对,可以同时指定多个分数/成员(score/member)对。
分数值是一个带符号带双精度浮点型数字字符串。
- 如果指定的成员已经在有序集合中,则会更新改成员的分数(scrore)并更新到正确的排序位置。
- 如果key不存在,将会创建一个新的有序集合(sorted set)并将分数/成员(score/member)对添加到有序集合。
历史
redis 版本 >= 2.4 时,ZADD
命令接受多个成员。 在Redis 2.4以前,ZADD
命令只能添加或者更新一个成员。
语法
ZADD key [NX|XX] [CH] [INCR] score1 member1 [score2 member2 ...]
score 是分数,放在前面 member 是成员
ZADD 参数
redis 版本 >= Redis 3.0.2时, ZADD支持以下参数
- XX : 只更新存在的成员,不添加新成员。
- NX : 不更新存在的成员。只添加新成员。
- INCR : 当指定这个参数时,成员的操作就等同
ZINCRBY
命令,对成员的分数进行递增操作,在此模式下只能指定一对分数/成员。 - CH : 这个参数有点意思,它的作用是改变返回值!!!
- 没有指定该参数时(默认情况下),返回的是新添加成员的总数,发生更新的成员不进行计数。
- 指定该参数后,返回的是发生变化的成员总数,即新添加的成员 + 发生更新的成员。(注意,如果一个成员已存在,并且分数也相同,则不会发生更新)
返回值
- 如果key存在,但是类型不是有序集合,将会返回一个错误应答。
- 如果指定了,INCR 参数,返回运算后的新分数
- 如果指定了,CH 参数, 返回的是发生变化的成员总数
- 同时指定 INCR 和 CH 参数,只要 INCR 生效,返回运算后的新分数
- 即没有指定 INCR 参数,又没有指定 CH 参数,返回新添加的成员总数
分数可以精确的表示的整数的范围
Redis 有序集合的分数使用双精度64位浮点数。我们支持所有的架构,这表示为一个IEEE 754 floating point number,它能包括的整数范围是-(2^53) 到 +(2^53)。或者说是-9007199254740992 到 9007199254740992。更大的整数在内部用指数形式表示,所以,如果为分数设置一个非常大的整数,你得到的是一个近似的十进制数。
分数和排序
Sorted Set 按照分数递增的方式进行排序。且不允许存在重复的成员。
分数可以通过ZADD
命令进行更新,也可以通过ZINCRBY
命令来修改之前的值,分数变化后,对应的成员的排序位置也会随之改变。
获取一个成员当前的分数可以使用ZSCORE
命令,也可以用它来验证成员是否存在。
相同分数的成员
有序集合里面的成员是不能重复的,但是不同成员间有可能有相同的分数。当多个成员有相同的分数时,将进行字典排序(ordered lexicographically)。
字典顺序排序用的是二进制,它比较的是字符串的字节数组。
如果用户将所有元素设置相同分数(例如0),有序集合里面的所有元素将按照字典顺序进行排序,范围查询元素可以使用ZRANGEBYLEX
命令
ZSCORE : 获取成员的分数
起始版本 : 1.2.0
时间复杂度 : O(1)
语法
ZSCORE key member
返回值
成员的分数,成员不存在返回nil
ZREM : 删除成员
起始版本 : 1.2.0
时间复杂度 : O(M*log(N)),其中N是有序集合中的元素数,M是要删除的元素数。
删除指定的成员key,不存在的成员将被忽略。
语法
ZREM key member [member ...]
返回值
删除的成员数,不包括不存在的成员。
历史
reids 版本 >= 2.4时,接受多个 member 参数
ZREMRANGEBYSCORE : 删除给定分数间的所有成员
起始版本 : 1.2.0
时间复杂度 : O(M + log(N)),其中N是有序集合中的元素数,M是要删除的元素数。
删除分数在 min 和之间 max 之间的所有成员,包括min也包括max
语法
ZREMRANGEBYSCORE key min max
返回值
删除的成员
ZREMRANGEBYRANK : 删除指定下标间的所有成员
起始版本 : 2.0.0
时间复杂度 : O(M + log(N)),其中N是有序集合中的元素数,M是要删除的元素数。
删除开始下标和结束下标之间的所有成员,下标从0开始,支持负下标,-1表示最右端成员,包括开始下标也包括结束下标
语法
ZREMRANGEBYSCORE key start stop
返回值
删除的成员
ZINCRBY : 增减成员的分数
起始版本 : 1.2.0
时间复杂度 : O(log(N)),其中N是有序集合中的元素数。
为有序集合中指定成员的分数加上一个带符号的双精度浮点数。
- 如果 key 不存在,先创建该有序集合
- 如果指定的成员不存在,先创建该成员,并初始化分数为0
score值必须是字符串表示的整数值或双精度浮点数,并且能接受double精度的浮点数。也有可能给一个负数来减少score的值。
语法
ZINCRBY key 带符号的双精度浮点数 member
返回值
- 相加后的分数
- 当key对应的value不是 Sorted Set 类型时,返回一个错误。
ZCARD : 获取集合中成员的个数
起始版本 : 1.2.0
时间复杂度 : O(1)
语法
ZCARD key
返回值
集合中成员的个数,如果key不存在,返回0
ZCOUNT : 获取集合在某个分数范围内的成员个数
起始版本 : 2.0.0
时间复杂度 : O(log(N)),其中N是有序集合中的元素数。
返回有序集合中,分数介于 min 和 max 之间的成员数量,包括min也包括max。
语法
ZCOUNT key min max
返回值
分数介于 min 和 max 之间的成员数量,如果key不存在,返回0
ZLEXCOUNT : 获取集合在某两个成员之间的成员个数
起始版本 : 2.8.9
时间复杂度 : O(log(N)),其中N是有序集合中的元素数。
返回有序集合中,介于 min 和 max 之间的成员数量。这里的 min 和 max 指的不是分数,而是成员。min 是分数小点的成员,max 是分数大点的成员,如果min成员的分数比max成员的分数还大,返回值为0
由于 Sorted Set 是有序集合(按分数从小到大排序),所以可以通过成员来搜索
语法
ZLEXCOUNT key min max
返回值
介于 min 和 max 之间的成员数量,包括min也包括max,如果key不存在,返回0
与 ZCOUNT的区别
ZLEXCOUNT
与 ZCOUNT
语法、作用、返回值都相同,区别在于
ZCOUNT
使用分数来圈定范围ZLEXCOUNT
使用成员来圈定范围(利用了 Sorted Set 是有序集合的性质)
ZPOPMAX : 删除分数最大成员(右端弹出)
起始版本 : 5.0.0
时间复杂度 : O(log(N) * M),其中N是排序集中元素的数量,M是弹出元素的数量。
删除并返回有序集合中 count 个分数最高的成员
- 如果 count 未指定,则默认值为1。
- 如果 count >= 有序集合中成员的数量,删除并返回(弹出)所有成员
当 count > 1时,分数最高的将是第一个,其次是分数较低的元素。如果分数最高的有多个,按排列循序,从右到左,删除并返回(弹出)。
官方的解释繁琐且不精确,这里说一下我的解释。由于 Sorted Set 是按照分数进行从小到大排序的,分数相同的按照成员的字节数组排序。所以 ZPOPMAX 的作用相当于右端弹出。
语法
ZPOPMAX key [count]
count 表示要弹出的个数
返回值
按照弹出循序的成员/分数对列表
ZPOPMIN : 删除分数最小成员(左端弹出)
起始版本 : 5.0.0
时间复杂度 : O(log(N) * M),其中N是排序集中元素的数量,M是弹出元素的数量。
左端弹出指定个数的成员/分数对
- 如果 count 未指定,则默认值为1
- 如果 count >= 有序集合中成员的数量,删除并返回(弹出)所有成员
语法
ZPOPMIN key [count]
count 表示要弹出的个数
返回值
按照弹出循序的成员/分数对列表
BZPOPMAX : (阻塞式)删除分数最大成员
起始版本 : 5.0.0
时间复杂度 : O(log(N)),其中N为有序集合中元素的数量
BZPOPMAX
是 ZPOPMAX
命令的阻塞版,当有序集合中没有成员时,会阻塞,指定有新成员添加进来或超时。
除此之外,BZPOPMAX
还可以指定多个key,当指定多个key时,按照参数中key的顺序,弹出第一个非空集合中分数最大的成员
语法
BZPOPMAX key1 [key2 ...] timeout
timeout 为超时时间,单位秒。设置为 0 表示无限超时
返回值
key名称、成员名称和分数,超时则返回 nil
BZPOPMIN : (阻塞式)删除分数最小成员
起始版本 : 5.0.0
时间复杂度 : O(log(N)),其中N为有序集合中元素的数量
BZPOPMIN
是 ZPOPMIN
命令的阻塞版,当有序集合中没有成员时,会阻塞,指定有新成员添加进来或超时。
除此之外,BZPOPMIN
还可以指定多个key,当指定多个key时,按照参数中key的顺序,弹出第一个非空集合中分数最小的成员
语法
BZPOPMIN key1 [key2 ...] timeout
timeout 为超时时间,单位秒。设置为 0 表示无限超时
返回值
key名称、成员名称和分数,超时则返回 nil
ZUNIONSTORE : 计算多个集合的并集,并保存
起始版本 : 2.0.0
时间复杂度 : O(N) + O(M log(M)),其中 N 是所有集合的成员数量之和,M 是结果集中元素的数量。
计算指定个数的给定有序集合的并集,并将结果存储在 destination 中。
必须提供 numkeys 参数,并且 numkeys 在 key 及其他可选参数之前
指定 WEIGHTS 参数,可以为每个有序集合指定一个权重。这意味着,在将每个有序集合中的成员分数传递给聚合函数之前,都要乘以该权重。如果 WEIGHTS 未指定,则权重默认为1。
指定 AGGREGATE 参数,可以指定如何合并并集的结果。默认使用 SUM 函数。当此选项设置为MIN或时MAX,结果集将选择最小或最大分数的成员。
语法
ZUNIONSTORE destination numkeys key1 [key2 ...] [WEIGHTS weight1 [weight2 ...]] [AGGREGATE SUM | MIN | MAX]
- destination : 目标集合,存放运算后的结果集。如果目标集合存在则覆盖。
- numkeys : 参与运算的集合数量(key的数量)
- WEIGHTS : 为每个集合指定权重,不指定时所有集合的权重默认为1。redis会将每个集合中的成员的分数 * 对应集合的权重
- AGGREGATE : 汇总算法,默认使用 SUM。
- SUM : 将同一成员的分数相加
- MIN : 取同一成员中分数最小的
- MAX : 取同一成员中分数最大的
返回值
结果集中元素的个数
ZINTERSTORE : 计算多个集合的交集,并保存
起始版本 : 2.0.0
时间复杂度 : O(N) + O(M log(M)),其中 N 是所有集合的成员数量之和,M 是结果集中元素的数量。
计算指定个数的给定有序集合的交集,并将结果存储在 destination 中。
语法
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM | MIN | MAX]
- destination : 目标集合,存放运算后的结果集。如果目标集合存在则覆盖。
- numkeys : 参与运算的集合数量(key的数量)
- WEIGHTS : 为每个集合指定权重,不指定时所有集合的权重默认为1。redis会将每个集合中的成员的分数 * 对应集合的权重
- AGGREGATE : 汇总算法,默认使用 SUM。
- SUM : 将同一成员的分数相加
- MIN : 取同一成员中分数最小的
- MAX : 取同一成员中分数最大的
返回值
结果集中元素的个数
ZRANK : 按分数从小到大获取成员在有序集合中的排名
起始版本 : 2.0.0
时间复杂度 : O(log(N))
按分数从小到大获取成员在有序集合中的排名,排名从0开始(也就是分数最小的排名为0,分数第二小的,排名为1...)
语法
ZRANK key member
返回值
成员对应的排名,如果key或成员不存在,返回nil
例子
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)
redis>
复制代码
ZREVRANK : 按分数从大到小获取成员在有序集合中的排名
起始版本 : 2.0.0
时间复杂度 : O(log(N))
按分数从大到小获取成员在有序集合中的排名,排名从0开始(也就是分数最大的排名为0,分数第二大的,排名为1...)
语法
ZREVRANK key member
返回值
成员对应的排名,如果key或成员不存在,返回nil
ZRANGE : 范围获取成员并按分数从小到大返回
起始版本 : 1.2.0
时间复杂度 : O(log(N) + M),N为有序集合中的元素数,M为返回的元素数。
返回开始下标和结束下标内的成员,并按照分数从小到大排序返回。
下标从0开始,支持负下标,-1表示最后一个成员,包括开始下标,也包括结束下标
由于 Sorted Set 是按分数从小到大排序,分数相同按成员字节数组排序,所以下标0表示最左边的成员,下表 -1 表示最右边的成员
下标超出范围不会产生错误。如果开始下标 > 集合最大下标或开始下标 > 结束下标,则结果为一个空列表。
如果结束下标 > 集合最大下标,则将结束下标视为集合的最大下标
语法
ZRANGE key start stop [WITHSCORES]
- start : 开始下标
- stop : 结束下标
- WITHSCORES :指定此参数时,除了会返回成员外,还会返回成员对应的分数
返回值
指定范围内的成员列表,如果指定了 WITHSCORES 参数,还会包含成员对应的分数。
列表顺序按分数从小到大排序,分数相同按成员字节数组排序
ZREVRANGE : 获取指定下标内的成员并按分数从大到小返回
起始版本 : 1.2.0
时间复杂度 : O(log(N) + M),N为有序集合中的元素数,M为返回的元素数。
返回开始下标和结束下标内的成员,并按照分数从大到小排序返回。
下标从0开始,支持负下标,-1表示最后一个成员,包括开始下标,也包括结束下标
由于 Sorted Set 是按分数从小到大排序,分数相同按成员字节数组排序,所以下标0表示最左边的成员,下表 -1 表示最右边的成员
下标超出范围不会产生错误。如果开始下标 > 集合最大下标或开始下标 > 结束下标,则结果为一个空列表。
如果结束下标 > 集合最大下标,则将结束下标视为集合的最大下标
ZREVRANGE 命令与 ZRANGE 命令唯一的不同就是返回列表的顺序
语法
ZREVRANGE key start stop [WITHSCORES]
- start : 开始下标
- stop : 结束下标
- WITHSCORES :指定此参数时,除了会返回成员外,还会返回成员对应的分数
返回值
指定范围内的成员列表,如果指定了 WITHSCORES 参数,还会包含成员对应的分数。
列表顺序按分数从大到小排序,分数相同按成员字节数组排序
ZRANGEBYSCORE : 获取分数范围内的成员并按从小到大返回
起始版本 : 1.0.5
时间复杂度 : O(log(N) + M),N为有序集合中的元素数,M为返回的元素数。如果M为常数(例如,始终要求使用LIMIT=10),则可以将其视为O(log(N))
返回分数在 min 和 max 之间的成员,包括min 也包括 max
语法
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
- min : 小分数
- max : 大分数
- WITHSCORES : 设置该参数后,除了返回成员外,还会返回成员的对应分数,该参数在 Redis 2.0 开始可用
- LIMIT offset count : 分页返回,offset 是结果集中的要返回成员的开始下标,count 是返回的条数,负数表示返回所有
返回值
成员列表,设置 WITHSCORES 参数后,还会返回成员的对应分数
列表顺序按分数从小到大排序,分数相同按成员字节数组排序
ZREVRANGEBYSCORE : 获取分数范围内的成员并按大到小返回
起始版本 : 2.2.0
时间复杂度 : O(log(N) + M),N为有序集合中的元素数,M为返回的元素数。如果M为常数(例如,始终要求使用LIMIT=10),则可以将其视为O(log(N))
返回分数在 min 和 max 之间的成员,包括min 也包括 max
此命令与 ZRANGEBYSCORE
命令的唯一区别在于,返回结果的排序
ZRANGEBYSCORE
按分数从小到大排序,分数相同按成员字节数组排序- 该命令按分数从大到小排序,分数相同按成员字节数组排序
语法
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
- max : 大分数
- min : 小分数
- WITHSCORES : 设置该参数后,除了返回成员外,还会返回成员的对应分数
- LIMIT offset count : 分页返回,offset 是结果集中的要返回成员的开始下标,count 是返回的条数,负数表示返回所有
返回值
成员列表,设置 WITHSCORES 参数后,还会返回成员的对应分数
列表顺序按分数从大到小排序,分数相同按成员字节数组排序