Redis:zset类型
- zset命令
- ZADD
- ZCARD
- ZCOUNT
- ZRANGE
- ZREVRANGE
- ZRANGEBYSCORE
- ZREVRANGEBYSCORE
- ZPOPMAX
- BZPOPMAX
- ZPOPMIN
- BZPOPMIN
- ZRANK
- ZREVRANK
- ZSCORE
- ZREM
- ZREMRANGEBYRANK
- ZREMRANGEBYSCORE
- ZINCRBY
- 集合间操作
- ZINRERSTORE
- ZUNIONSTORE
- 内部编码
- ziplist
- skiplist
在Redis中,有两种集合类型,set和zset,其中set是无序集合,zset是有序集合,本博客讲解Redis中的有序集合。
在有序集合中,要按照一定的指标给集合元素进行排序,Redis个每个集合的元素引入了一个score属性,这是一个双精度浮点型,每次排序的时候,依据socre的大小进行排序。如果分数相同,那么以字典序排序。
zset命令
ZADD
- 往
zset中添加元素和分数
zadd key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
选项:
[XX|NX]XX:只更新,如果element或者key不存在,操作失败NX:只添加,如果element或者key不存在,添加数据,如果存在,操作失败
[GT|LT]LT:如果新的socre小于(Less Than)当前的score,那么更新元素GT:如果新的socre大于(Greater Than)当前的score,那么更新元素
[CH]不加CH:zadd返回新增的元素个数加CH:zadd返回修改的元素个数
[INCR]:对现有的socre进行运算
示例:

此处插入了四个数据,随后通过zrange查询结果(后面讲),可以看到输出结果是以score排序的。

还可以通过zadd更新数值,把mike的值提升到80.5后,再次查询顺序就变了。

此处演示ch的功能,第一次先通过add添加了两个成员lora和meg。第二次修改lora和meg的score,结果返回值为0,这不是说明修改失败了,而是其只返回新增元素个数,而不是修改的元素个数。第三次修改lora和meg的score,并且加入ch选项,返回2说明有两个元素修改成功了。

第一次通过zadd设置peter的score为100,第二次添加incr选项,表示在当前的score基础上再加20,返回120为增加后的结果。
ZCARD
- 获取
zset的元素个数
zcard key
返回zset的元素个数。
ZCOUNT
- 返回指定区间内的元素个数
zcount key min max
返回score在[min, max]闭区间的元素个数,可以通过(min (max来设置开区间。

在zset3中,有五个分数12 20 42 68 88。第一次查询20 68,在闭区间内有三个数值,返回3。第二次查询(20 68,表示左开右闭区间,第三次查询(20 (68表示开区间,第四次查询20 (68表示左闭右开区间。
此处实现计数,不是查询到min和max后,遍历区间内的元素然后计数。在zset内部,会给每个元素存储其当前的排名,查询到min和max后,直接将两者的排名做差就可以得到count。
另外的,区间还支持浮点数的负无穷大-inf和正无穷大inf。

这种格式就是统计zset中所有元素个数。
ZRANGE
- 返回指定区间内的元素,按升序排序
zrange key start stop [withscores]
按升序返回[start, stop]区间内的元素,如果带上withscores则将score一起返回。
此处的start和stop不是分数,而是元素的排名,从0开始,支持负数。
示例:


加上withcores参数后,每个元素的下一行是它的socre。
ZREVRANGE
- 返回指定区间内的元素,按降序排序
zrevrange key start stop [withscores]
按降序返回[start, stop]区间内的元素,如果带上withscores则将score一起返回。
此处的rev表示reverse翻转,只是将原先的输出顺序颠倒了一下,用法和zrange没有区别。
ZRANGEBYSCORE
- 返回指定区间内的元素,按升序排序
zrangebyscore key min max [withscores]
按升序返回score在[min, max]区间内的元素,如果带上withscores则将score一起返回。
之前的zrange是通过元素排名返回,zrangebyscore则是通过score区间返回。
示例:

注意:官方文档表明,该命令即将被废弃,并且功能会合并到zrange中。
ZREVRANGEBYSCORE
- 返回指定区间内的元素,按降序排序
zrevrangebyscore key min max [withscores]
按降序返回score在[min, max]区间内的元素,如果带上withscores则将score一起返回。
只是将输出顺序颠倒了一下,用法和zrangebyscore一样。
注意:官方文档表明,该命令即将被废弃,并且功能会合并到zrevrange中。
ZPOPMAX
- 获取并删除
score最高的多个元素
zpopmax key [count]
返回当前的count个最大元素,并且将这些元素从zset中删除。
示例:

如果多个元素的score相同,那么会按照member的字典序进行比较,字典序高的先删除。
BZPOPMAX
- 读取并删除
zset最大元素,如果没有元素则陷入阻塞
bzpopmax key [key ...] timeout
bzpopmax 可以同时指定多个key,也就是多个zset,只要任何一个zset有数据,就返回结果。还可以设置超时时间timeout,以秒为单位,如果超过时间了,返回nil。
如果超时时间设置为0,则一直阻塞,不会超时。
示例:

此处启动了两个终端,左侧终端通过bzpopmax读取zset1的最大值。但是由于zset1内没有元素陷入阻塞。不久后在右侧终端插入66 lisa,此时左侧终端检测到后,立刻返回结果。zset1表示自己读取到的数据属于哪一个zset,lisa是member,66是score。
ZPOPMIN
- 获取并删除
score最小的多个元素
zpopmin key [count]
返回当前的count个最小元素,并且将这些元素从zset中删除。
BZPOPMIN
- 读取并删除
zset最小元素,如果没有元素则陷入阻塞
bzpopmin key [key ...] timeout
bzpopmin 可以同时指定多个key,也就是多个zset,只要任何一个zset有数据,就返回结果。还可以设置超时时间timeout,以秒为单位,如果超过时间了,返回nil。
如果超时时间设置为0,则一直阻塞,不会超时。
ZRANK
- 获取指定元素的排名
zrank key member
返回指定元素member的排名,这个排名就是socre从小到大的顺序,从0开始排,也可以当作下标。
示例:

此处排名最前的是lisa,下标为0。
ZREVRANK
- 获取指定元素的排名
zrevrank key member
返回指定元素member的排名,这个排名就是socre从大到小的顺序,从0开始排。
示例:

ZSCORE
- 获取指定元素的分数
zscore key member
返回指定元素member的分数。
ZREM
- 删除指定元素
zrem key member [member ...]
返回成功删除的元素个数。
ZREMRANGEBYRANK
- 根据排名,删除指定区间内的元素
zremrangebyrank key start stop
删除排名在[start, stop]闭区间范围内的元素,返回成功删除的元素个数。
示例:

ZREMRANGEBYSCORE
- 根据
score,删除指定区间内的元素
zremrangebyscore key min max
删除分数在[min, max]闭区间范围内的元素,返回成功删除的元素个数。
示例:

ZINCRBY
- 为指定元素的
score增加指定的值
zincrby key increment member
给member的score增加increment的值,返回增加后的结果,increment可以为负值和浮点数。
集合间操作
在set中,提供了sinter、sunion、sdiff处理交集、并集、差集。那么zset是否也有对应的zinter、zunion、zdiff?是有的,但是在Redis 6.2后才开始支持,在那之前,zset只提供了两个集合间操作。
ZINRERSTORE
- 求多个集合的交集,结果保存到指定
zset中
zinterstore destination numkeys key [key ...] [weights weight [weight ...]] [aggregate <sum | min | max>]
destination:输出结果到给zset中numkeys:指定后续输入的key的个数weights:权重,每一个zset都配一个weight,计算时score乘对应的weightaggreate:score的合并方式sum:求和(默认值)min:取最小max:取最大
示例:

此处创建了两个zset,通过zinterstore合并,其中zset1的权重是1,zset2的权重是100,以sum方式合并。最后求出交集bob 1 * 100 + 20,lisa 3 * 100 + 12。
ZUNIONSTORE
- 求多个集合的并集,结果保存到指定
zset中
zunionstore destination numkeys key [key ...] [weights weight [weight ...]] [aggregate <sum | min | max>]
这个参数和zinterstore完全一致,只是从交集变成并集。
- 总结:
| 命令 | 功能 |
|---|---|
zadd | 往zset中添加元素和分数 |
zcard | 获取zset的元素个数 |
zcount | 计算在指定分数范围内的元素个数 |
zrange | 获取指定区间内的元素 |
zrevrange | 获取指定区间内的元素(按分数从高到低) |
zrangebyscore | 获取指定分数范围内的元素 |
zrevrangebyscore | 获取指定分数范围内的元素(按分数从高到低) |
zpopmax | 弹出zset中分数最高的元素 |
bzpopmax | 阻塞弹出zset中分数最高的元素 |
zpopmin | 弹出zset中分数最低的元素 |
bzpopmin | 阻塞弹出zset中分数最低的元素 |
zrank | 获取元素在zset中的排名(按分数从小到大) |
zrevrank | 获取元素在zset中的排名(按分数从大到小) |
zscore | 获取元素在zset中的分数 |
zrem | 移除zset中的一个或多个元素 |
zremrangebyrank | 移除zset中给定排名区间的元素 |
zremrangebyscore | 移除zset中给定分数区间的元素 |
zincrby | 增加zset中元素的分数 |
zinterstore | 计算两个或多个zset的交集,并将结果存储在新的zset中 |
zunionstore | 计算两个或多个zset的并集,并将结果存储在新的zset中 |
内部编码
ziplist
当有序集合的元素个数小于zset-max-ziplist-entries配置(默认128个),同时每个元素的值都⼩于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使⽤。
skiplist
当ziplist条件不满⾜时,有序集合会使用skiplist作为内部实现,因为此时ziplist的操作效率会下降。
跳表是一种搜索结构,搜索时间复杂度为O(lgN),与平衡二叉搜索树是一个级别。


















