【Redis】Zset 有序集合

article/2025/7/6 17:50:28

文章目录

  • 常用命令
    • zadd
    • zcard
    • zcount
    • zrange && zrevrange
    • zrangebyscore
    • zpopmax && bzpopmax
    • zpopmin && zpopmax
    • zrank && zrevrank
    • zscore
    • zrem
    • zremrangebyrank
    • zremrangebyscore
    • zincrby
  • 集合间操作
    • 交集 zinterstore
    • 并集 zunionstore
  • 内部编码
  • 应用场景

在这里插入图片描述

有序集合和集合(Set)一样,不能有重复成员,但与之不同的是,有序集合中的每个元素都有一个唯一的浮点类型的分数(score),通过这个分数实现有序性

在这里插入图片描述
有序集合提供了获取指定分数和元素范围查找、计算成员排名等功能

有序集合中的元素是不能重复的,但分数可以相同。若分数相同,则按元素的字典序排序

常用命令

zadd

添加或者更新指定的元素以及关联的分数到 zset ,分数应该符合 double 类型,+inf / -inf 作为正负极限也是合法的

相关选项:

  • XX:当元素存在时才生效,即用于更新已经存在的元素,不会添加新元素
  • NX:当元素不存在时才生效,即用于添加新元素
  • CH:默认情况下,zadd 的返回值时本次新添加的元素个数,使用该选项,返回值还会包含本次操作更新的元素的个数
  • INCR:将元素的分数加上指定的分数,可正可负。此时只能指定一个元素和分数

zadd key [NX | XX] [CH] [INCR] score member [score member…]

返回值:本次添加成功的元素;如果使用了 INCR,则返回值为修改后的分数

示例:

127.0.0.1:6379> zadd key1 95 zhangsan 92 lisi 97 wangwu 77 zhaoliu
(integer) 4127.0.0.1:6379> zadd key1 94 zhangsan
(integer) 0 # 修改默认不计入返回值# 查看 zset 元素
127.0.0.1:6379> zrange key1 0 -1 withscores
1) "zhaoliu"
2) "77"
3) "lisi"
4) "92"
5) "zhangsan"
6) "94"
7) "wangwu"
8) "97"# 修改并将修改成功的元素个数计入返回值
127.0.0.1:6379> zadd key1 XX CH 99 zhangsan
(integer) 1
127.0.0.1:6379> zrange key1 0 -1 withscores
1) "zhaoliu"
2) "77"
3) "lisi"
4) "92"
5) "wangwu"
6) "97"
7) "zhangsan"
8) "99"# 减少分数
127.0.0.1:6379> zadd key1 incr -4 zhangsan
"95"

zcard

获取 zset 的基数(cardinality),即 zset 中的元素个数

zcard key

返回值:zset 的元素个数

示例:

127.0.0.1:6379> zcard key1
(integer) 4

zcount

返回分数在 min 和 max 之间的元素个数,默认情况下,是包含 min 和 max,但可以通过( 排除

zcount key [(]min [(]max

返回值:满足条件的元素个数
时间复杂度:O(log(N))

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "zhaoliu"
2) "77"
3) "lisi"
4) "92"
5) "zhangsan"
6) "95"
7) "wangwu"
8) "97"# 包含分数 7795
127.0.0.1:6379> zcount key1 77 95
(integer) 3
# 不包含分数 77
127.0.0.1:6379> zcount key1 (77 95
(integer) 2
# 不包含分数 7795
127.0.0.1:6379> zcount key1 (77 (95
(integer) 1

zrange && zrevrange

zrange

返回指定区间的元素,升序
withscores 选项可以把分数也返回

zrange key start stop [withscores]
[start, stop] 为闭区间,下标从0开始,支持负数,-1表示倒数第一个数,以此类推

时间复杂度:O(log(N) + M),N为元素总个数,M为区间元素个数

示例:

# 查询从下标0到最后一个
127.0.0.1:6379> zrange key1 0 -1
1) "zhaoliu"
2) "lisi"
3) "zhangsan"
4) "wangwu"
# 携带上分数
127.0.0.1:6379> zrange key1 0 -1 withscores
1) "zhaoliu"
2) "77"
3) "lisi"
4) "92"
5) "zhangsan"
6) "95"
7) "wangwu"
8) "97"
# 查询下标13
127.0.0.1:6379> zrange key1 1 3 withscores
1) "lisi"
2) "92"
3) "zhangsan"
4) "95"
5) "wangwu"
6) "97"

zrevrange

返回指定区间的元素,降序
withscores 选项可以携带分数返回

PS:该命令可能在 6.2.0后废弃,功能合并到 zrange 中

zrevrange key start stop [withscores]

时间复杂度:O(log(N) + M),N为元素总个数,M为区间元素个数

示例:

127.0.0.1:6379> zrevrange key1 0 -1 withscores
1) "wangwu"
2) "97"
3) "zhangsan"
4) "95"
5) "lisi"
6) "92"
7) "zhaoliu"
8) "77"
127.0.0.1:6379> zrevrange key1 1 3 withscores
1) "zhangsan"
2) "95"
3) "lisi"
4) "92"
5) "zhaoliu"
6) "77"

zrangebyscore

返回分数在 min 和 max 之间的元素,默认是闭区间,可以通过(排除
PS:该命令可能在6.2.0后废除,功能合并到 zrange 中

zrangebyscore key min max [withscores]

时间复杂度:O(log(N)+M)

示例:

127.0.0.1:6379> zrangebyscore key1 -inf +inf withscores
1) "zhaoliu"
2) "77"
3) "lisi"
4) "92"
5) "zhangsan"
6) "95"
7) "wangwu"
8) "97"
127.0.0.1:6379> zrangebyscore key1 (92 +inf withscores
1) "zhangsan"
2) "95"
3) "wangwu"
4) "97"

zpopmax && bzpopmax

zpopmax

删除并返回分数最高的 count 个元素

zpopmax key [count]

时间复杂度:O(log(N) * M),删除一个元素为log(N),M为要删除的元素个数
返回值:分数和元素列表

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "zhaoliu"
2) "77"
3) "lisi"
4) "92"
5) "zhangsan"
6) "95"
7) "wangwu"
8) "97"
127.0.0.1:6379> zpopmax key1 2
1) "wangwu"
2) "97"
3) "zhangsan"
4) "95"

bzpopmax

zpopmax 的阻塞版本

bzpopmax key [key…] timeout

时间复杂度:O(log(N));源码虽然有记录最大元素,但还是套用了删除一个元素的算法,所以时间复杂度不是O(1),而是O(log(N))
返回值:zset、元素、分数

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "zhaoliu"
2) "77"
3) "lisi"
4) "92"
127.0.0.1:6379> zrange key2 0 -1 withscores
1) "wangwu"
2) "100"
127.0.0.1:6379> bzpopmax key1 key2 10
1) "key1"
2) "lisi"
3) "92"

按顺序检查有序集合是否有元素,有则删除最大,无则检查下一个有序集合,只要删除一个元素就结束,所以并不是删除所有有序结合的最大值,而是最先有元素的有序集合的最大值

zpopmin && zpopmax

zpopmin

大致与 zpopmax 相同,不过时删除最小元素

删除并返回分数最低的 count 个元素

zpopmin key [count]

时间复杂度:O(log(N) * M)
返回值:分数和元素列表

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "zhaoliu"
2) "77"
3) "zhangsan"
4) "88"
5) "lisi"
6) "99"
127.0.0.1:6379> zpopmin key1 2
1) "zhaoliu"
2) "77"
3) "zhangsan"
4) "88"

bzpopmin

zpopmin 的阻塞版本

bzpopmin key [key…] timeout

时间复杂度:O(log(N))
返回值:zset、元素、分数

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
(empty array)
127.0.0.1:6379> zrange key2 0 -1 withscores
1) "zhangsan"
2) "95"
3) "wangwu"
4) "100"
127.0.0.1:6379> bzpopmin key1 key2 10
1) "key2"
2) "zhangsan"
3) "95"

zrank && zrevrank

zrank
返回指定元素的排名,升序

zrank key member

时间复杂度:O(log(N))

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "lisi"
2) "48"
3) "wangwu"
4) "83"
5) "zhaoliu"
6) "92"
7) "zhangsan"
8) "94"
127.0.0.1:6379> zrank key1 zhangsan
(integer) 3
127.0.0.1:6379> zrank key1 lisi
(integer) 0

zrevrank

返回指定元素的排名,降序

zrevrank key member

时间复杂度:O(log(N))

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "lisi"
2) "48"
3) "wangwu"
4) "83"
5) "zhaoliu"
6) "92"
7) "zhangsan"
8) "94"
127.0.0.1:6379> zrevrank key1 zhangsan
(integer) 0
127.0.0.1:6379> zrevrank key1 lisi
(integer) 3

zscore

获取指定元素的分数

zscore key member

时间复杂度:O(1)

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "lisi"
2) "48"
3) "wangwu"
4) "83"
5) "zhaoliu"
6) "92"
7) "zhangsan"
8) "94"
127.0.0.1:6379> zscore key1 zhangsan
"94"
127.0.0.1:6379> zscore key1 lisi
"48"

zrem

删除指定的元素

zrem key member [member…]

时间复杂度:O(log(N) * M),删除一个元素为O(log(N)),M为要删除的元素个数
返回值:本次操作删除的元素个数

示例:

127.0.0.1:6379> zrem key1 zhangsan lisi
(integer) 2

zremrangebyrank

按照排序,升序删除指定范围的元素,左闭右闭

zremrangebyrank key start stop

时间复杂度:O(log(N) + M)
返回值:本次操作删除的元素个数

示例:

127.0.0.1:6379> zrange key 0 -1
1) "zhaoliu"
2) "zhangsan"
3) "lisi"
4) "wangwu"
127.0.0.1:6379> zremrangebyrank key 0 1
(integer) 2
127.0.0.1:6379> zrange key 0 -1
1) "lisi"
2) "wangwu"

zremrangebyscore

按照分数删除指定范围的元素,左闭右闭

zremrangebyrank key min max

时间复杂度:O(log(N) + M)
返回值:本次操作删除的元素个数

示例:

127.0.0.1:6379> zrange key 0 -1
1) "lisi"
2) "wangwu"
127.0.0.1:6379> zremrangebyscore key -inf +inf
(integer) 2

zincrby

给指定的元素添加指定分数,可正可负

zincrby key increment member

时间复杂度:O(log(N))
返回值:修改后元素的分数

示例:

127.0.0.1:6379> zadd key 88 zhangsan
(integer) 1
127.0.0.1:6379> zincrby key 8 zhangsan
"96"
127.0.0.1:6379> zincrby key -4 zhangsan
"92"

集合间操作

Zset 提供交集和并集操作

交集 zinterstore

交集时提取多个 Zset 共有的元素,但因为还是分数(score),所以需要指定提取后的分数如何取值。
同时 Zset 还提供权重(weight)

zinterstore destination numkeys key [key…] [weights weight] [aggregate sum | min | max]

  • destination:将并集的结果保存在目标 Zset 中
  • numkeys:并集的 Zset 个数
  • weight:权重,浮点类型,个数应和 numkeys 相同
  • aggregate:并集的分数组成,可选 sum | min | max,默认是 sum

在这里插入图片描述

时间复杂度:O(N * K) + O(M * log(M));N 是输入的有序集合中,最小的有序集合的元素个数;K是输入了几个有序集合;M是最终结果的有序集合的元素个数
返回值:并集的元素个数

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "c"
2) "2"
3) "a"
4) "5"
5) "b"
6) "8"
7) "d"
8) "14"
127.0.0.1:6379> zrange key2 0 -1 withscores
1) "d"
2) "6"
3) "f"
4) "7"
5) "c"
6) "8"
7) "e"
8) "13"# 分数默认以 sum
127.0.0.1:6379> zinterstore key3 2 key1 key2
(integer) 2
127.0.0.1:6379> zrange key3 0 -1 withscores
1) "c"
2) "10"
3) "d"
4) "20"# 分数以 max
127.0.0.1:6379> zinterstore key4 2 key1 key2 aggregate max
(integer) 2
127.0.0.1:6379> zrange key4 0 -1 withscores
1) "c"
2) "8"
3) "d"
4) "14"# 分数乘以权重
127.0.0.1:6379> zinterstore key5 2 key1 key2 weights 4 6
(integer) 2
127.0.0.1:6379> zrange key5 0 -1 withscores
1) "c"
2) "56"
3) "d"
4) "92"

并集 zunionstore

zunionstore destination numkeys key [key…] [weights weight…] [aggregate sum | min | max]

在这里插入图片描述

时间复杂度:O(N) + O(M * log(M));N 是输入的有序集合总的元素个数;M是最终结果的有序集合的元素个数

示例:

127.0.0.1:6379> zrange key1 0 -1 withscores
1) "c"
2) "2"
3) "a"
4) "5"
5) "b"
6) "8"
7) "d"
8) "14"
127.0.0.1:6379> zrange key2 0 -1 withscores
1) "d"
2) "6"
3) "f"
4) "7"
5) "c"
6) "8"
7) "e"
8) "13"
127.0.0.1:6379> zunionstore key3 2 key1 key2
(integer) 6
127.0.0.1:6379> zrange key3 0 -1 withscores1) "a"2) "5"3) "f"4) "7"5) "b"6) "8"7) "c"8) "10"9) "e"
10) "13"
11) "d"
12) "20"
127.0.0.1:6379> zunionstore key4 2 key1 key2 aggregate min
(integer) 6
127.0.0.1:6379> zrange key4 0 -1 withscores1) "c"2) "2"3) "a"4) "5"5) "d"6) "6"7) "f"8) "7"9) "b"
10) "8"
11) "e"
12) "13"
127.0.0.1:6379> zunionstore key5 2 key1 key2 weights 0.2 0.5
(integer) 6
127.0.0.1:6379> zrange key5 0 -1 withscores1) "a"2) "1"3) "b"4) "1.6000000000000001"5) "f"6) "3.5"7) "c"8) "4.4000000000000004"9) "d"
10) "5.8000000000000007"
11) "e"
12) "6.5"

在这里插入图片描述

内部编码

有序集合的内部编码有两种:

  • ziplist(压缩列表):当有序集合的元素个数小于 zset-max-ziplist-entries,同时每个元素的值都小于 zset-max-ziplist-value 时,ziplist 为其内部实现,可以有效减少内存的使用
  • skiplist(跳表):不满足上述条件时,使用 skiplist 作为内部实现,因为此时 ziplist 的操作效率会下降

应用场景

有序集合比较典型的使用场景就是排行榜系统。例如常见的网站上的热榜信息,榜单的维度可能时多方面的:按照时间、阅读量、点赞量。

例如,通过点赞维护热榜

  1. 添加用户赞数
    例如用户 zhangsan 发布了一篇文章,获得了3个点赞,添加使用 zadd,后续获赞使用 zincrby
zadd user:ranking:2025-06-02 3 zhangsan
zincrby user:ranking:2025-06-02 2 zhangsan
  1. 取消用户赞数
    由于各种原因(如用户删除文章,作弊),此时需要将用户从榜单删除,使用 zrem
zrem user:ranking:2025-06-02 zhangsan
  1. 展示获赞数最多的10个用户,可以使用 zrevrange
zrevrangebyrank user:ranking:2025-06-02 0 9
  1. 展示用户信息以及用户分数
zscore user:ranking:2025-06-02 lisi
zrank user:ranking:2025-06-02 lisi

以上就是本篇博客的所有内容,感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述


http://www.hkcw.cn/article/nRDqTMQGtm.shtml

相关文章

【AI论文】视觉语言模型中的自我修正推理

摘要:推理视觉语言模型(VLMs)在复杂的多模态任务上表现出了良好的性能。 然而,它们仍然面临着重大挑战:它们对推理错误高度敏感,需要大量带注释的数据或精确的验证器,并且难以在特定领域之外进行…

正则表达式在Java中的应用(补充)

正则表达式在Java中的应用 Java通过java.util.regex包提供正则表达式支持,核心类包括Pattern和Matcher。Pattern用于编译正则表达式模式,Matcher用于匹配操作。基本语法遵循标准正则规则,如\d匹配数字,\w匹配单词字符。 Pattern…

C++ 内存泄漏检测器设计

文章目录 1. C中的动态内存分配2. 什么是内存泄漏3. 内存泄漏的代码案例4. 内存泄漏检查器的设计模块1:位置信息捕获:模块2:内存分配跟踪:模块3:内存释放跟踪:模块4:泄漏记录存储:模…

线程安全与线程池

概念:多个线程,同时操作同一个共享资源的时候,可能会出现业务安全问题。 出现线程安全问题的条件,原因:1.存在多个线程在同时执行 2.同时访问一个共享资源 3.存在修改该共享资源 线程同步:是线程安全…

网络安全的学习路线是怎么样的?

我是几乎完全自学的,十年前从双非跨专业考研到中科大软件学院网络安全专业,读研之前,C语言是自学的,数据结构是自学的,计算机网络是自学的,操作系统是自学的,微机原理是自学的。为了让我们能跟上…

每日算法-250602

每日算法学习记录 - 250602 今天学习和复习了两道利用前缀和与哈希表解决的子数组问题,特此记录。 560. 和为 K 的子数组 题目 思路 本题的核心思想是利用 前缀和 与 哈希表 来优化查找过程。 解题过程 题目要求统计和为 k 的子数组个数。 我们首先预处理出一…

Hadoop学习笔记

(1)Hadoop概述 Hadoop是一个开源的分布式计算和存储框架,用于处理大规模数据集(大数据)的并行处理。它由Apache基金会开发,核心设计灵感来自Google的MapReduce和Google文件系统(GFS&#xff09…

PCIe—TS1/TS2 之Polling.Configuration (二)

前文 在 Polling.Configuration 次状态中,发送⽅停⽌发送 TS1 序列,转⽽发送 TS2 序列,TS2 序列中的链路和通道(lane)字段仍然使⽤填充字段填充。 该状态中,发送⽅转⽽发送 TS2 的⽬的是通知链路对端的设备…

如何增加 cPanel中的 PHP 最大上传大小?

PHP通过限制文件上传大小来保护服务器性能,但默认限制对于许多现代网页应用来说太低了。当PHP应用程序显示错误信息,要求你增加PHP的最大上传文件大小时,你可能会遇到这个问题。有多种方法可以提高上传限制,包括直接编辑PHP配置文…

linux——文件系统

被打开的文件放到内存中没有被打开的文件放到磁盘 1. 硬件-->磁盘 磁盘的存储基本单位:扇区(512字节) 512字节写入到磁盘,磁盘如何转动: 磁盘写入的时候是向柱面进行批量写入的 CHS地址:cylind heade…

HBM的那些事2 写操作

搞懂写,把下面这幅图搞定,基本上就掌握了7成了。 术语解释 WL : write latency,说的是命令到发送数据的WDQS的间隔,注意这里不包含twpre1的时间,通过配置MR1实现。 twpre1: 在发送写数据之前,W…

B1039 PAT乙级JAVA题解 到底买不买

小红想买些珠子做一串自己喜欢的珠串。卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖。于是小红要你帮忙判断一下,某串珠子里是否包含了全部自己想要的珠子?如果是,那么告诉她有多少多余的珠子;如果…

力扣HOT100之多维动态规划:62. 不同路径

这道题用二维dp数组来做相当简单,是一道入门题。直接上动规五部曲: 1.确定dp[i][j]的含义:从起点到位置为[i][j]处的路径总数 2.确定递推公式 dp[i][j] dp[i - 1][j] dp[i][j - 1]; 3.dp数组初始化 dp[0][j] 1;dp[i][0] 1; 4.确定遍历顺序…

css呼吸灯

效果图 只是简单的呼吸效果,您按照需求自己拓展即可。 代码 keyframes light{from{opacity: 1;}to{opacity: 0.2;}}使用 .view{animation-name: light;animation-duration: 1s;animation-timing-function: linear;animation-iteration-count: infinite;animation-…

AI入门——AI大模型、深度学习、机器学习总结

以下是对AI深度学习、机器学习相关核心技术的总结与拓展,结合技术演进逻辑与前沿趋势,以全新视角呈现关键知识点 一、深度学习:从感知到认知的技术革命 核心突破:自动化特征工程的范式变革 深度学习通过多层神经网络架构&#x…

python训练营打卡第42天

Grad-CAM与Hook函数 知识点回顾 回调函数lambda函数hook函数的模块钩子和张量钩子Grad-CAM的示例 作业:理解下今天的代码即可 1.回调函数 def handle_result(result):"""处理计算结果的回调函数"""print(f"计算结果是: {resul…

ISO18436-2 CATII级振动分析师能力矩阵

ISO18436-2021是当前针对针对分析师的一个标准,它对振动分析师的能力和知识体系做了4级分类,这里给出的是一家公司响应ISO18436的CATII级标准,做的一个专题培训的教学大纲。摘自: 【振動噪音產學技術聯盟】04/19-23 ISO 18436-2…

YARN应用日志查看

YARN应用日志查看 1、页面查看2、命令行查看1、页面查看 1.1、YARN ResourceManager Web UI Spark on YARN时,YARN的资源管理器(ResourceManager)和历史服务器(History Server)提供了强大的日志和监控功能,可以帮助用户查看和管理Spark作业 访问YARN ResourceManager的…

免费酒店管理系统+餐饮系统+小程序点餐——仙盟创梦IDE

酒店系统主屏幕 房间管理 酒店管理系统的房间管理,可实现对酒店所有房间的实时掌控。它能清晰显示房间状态,如已预订、已入住、空闲等,便于高效安排入住与退房,合理分配资源,提升服务效率,保障酒店运营有条…

29 C 语言内存管理与多文件编程详解:栈区、全局静态区、static 与 extern 深度解析

1 C 语言内存管理概述 1.1 内存分区模型解析 在 C 语言程序中,内存的合理管理是确保程序高效运行的核心。为了深入理解变量的作用域、生命周期及内存分配机制,我们需要先掌握内存分区模型。C 语言将内存划分为以下几个核心区域: 栈区&#…