ZSet
一、ZSet 类型概述
Redis 的 Sorted Set 是一个 有序的、不重复的 字符串集合,结合了 Set 的唯⼀性和 List 的有序性。每个元素都会关联一个 score
(分数),Redis 正是通过分数来为集合中的元素进行 从小到大 的排序。
核心特点:
- 元素唯一:集合中的元素(member)不重复
- 有序性:元素按照 score 排序
- 分数可重复:不同元素可以有相同的 score
二、基本方法
- 添加更新与删除元素
-
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score1 member1 [score2 member2 ...]
:添加元素NX
:只添加新元素,不更新已存在的XX
:只更新已存在的元素,不添加新元素INCR
:对 score 进行增加操作CH
:返回被修改的元素数量
bash
127.0.0.1:6379> zadd name 1 xiaozhang #添加元素并设置score
(integer) 1
127.0.0.1:6379> zadd name 2 zhangxiao
(integer) 1
127.0.0.1:6379> zadd name nx 3 xiaozhang
(integer) 0
127.0.0.1:6379> zadd name xx ch 3 xioazhang #没有元素,更新失败
(integer) 0
127.0.0.1:6379> zadd name xx ch 3 xiaozhang
(integer) 1
127.0.0.1:6379> zadd name xx ch 4 xiaozhang
(integer) 1
127.0.0.1:6379> zrem name xiaozhang #删除一个或多个元素
(integer) 1
127.0.0.1:6379> zrange name 0 -1
1) "zhangxiao"
- 查询元素
bsah
127.0.0.1:6379> zadd map 1 one 2 twe 3 three 4 four
(integer) 4
127.0.0.1:6379> zrange map 0 -1 #按score升序获取所有的元素
1) "one"
2) "twe"
3) "three"
4) "four"
127.0.0.1:6379> zrange map 0 -1 withscores #按score升序获取所有的元素及score
1) "one"
2) "1"
3) "twe"
4) "2"
5) "three"
6) "3"
7) "four"
8) "4"
127.0.0.1:6379> zrevrange map 0 -1 #按score降序获取所有的元素
1) "four"
2) "three"
3) "twe"
4) "one"
127.0.0.1:6379> zrangebyscore map 0 2 #返回指定分数范围的元素
1) "one"
2) "twe"
127.0.0.1:6379> zrangebyscore map 0 2 withscores
1) "one"
2) "1"
3) "twe"
4) "2"
127.0.0.1:6379> zrevrangebyscore map 3 2 #降序返回指定分数范围的元素
1) "three"
2) "twe"
127.0.0.1:6379> zrevrangebyscore map 3 2 withscores
1) "three"
2) "3"
3) "twe"
4) "2"
- 统计与排名操作
bash
127.0.0.1:6379> zadd map 1 one 2 twe 3 three 4 four
(integer) 4
127.0.0.1:6379> zcard map #统计集合中的元素数
(integer) 4
127.0.0.1:6379> zcount map -inf +inf #获取集合某个区间中有多少元素(-inf表示负无穷,+inf表示正无穷)
(integer) 4
127.0.0.1:6379> zcount map 2 3
(integer) 2
127.0.0.1:6379> zrank map twe #获取元素的升序排名
(integer) 1
127.0.0.1:6379> zrank map twe withscore #获取元素的升序排名及对应的score
1) (integer) 1
2) "2"
127.0.0.1:6379> zrevrank map twe #获取元素的降序排名
(integer) 2
127.0.0.1:6379> zrevrank map twe withscore #获取元素的降序排名及对应的score
1) (integer) 2
2) "2"
127.0.0.1:6379> zscore map three #获取元素的score
"3"
- 集合操作
bash
127.0.0.1:6379> zadd num 1 v1 2 v2 3 v3 4 v4
(integer) 4
127.0.0.1:6379> zadd count 3 v3 4 v4 5 v5 6 v6
(integer) 4
127.0.0.1:6379> zunion 2 num count #获取并集
1) "v1"
2) "v2"
3) "v5"
4) "v3"
5) "v6"
6) "v4"
127.0.0.1:6379> zinter 2 num count #获取交集
1) "v3"
2) "v4"
三、内部实现
zset 的底层实现根据元素数量和大小自动选择:
-
ziplist
(压缩列表) :- 当元素数量较少(默认 ≤ 128),且所有元素长度较小(默认 ≤ 64 字节)时使用
- 内存紧凑,按 score 排序存储
-
skiplist
(跳跃表) +dict
(字典) :- 当不满足 ziplist 条件时使用
skiplist
用于按 score 排序和范围查询dict
用于 O(1) 时间复杂度的元素查找
四、ZSet 类型的应用场景
排行榜系统 :最经典的用法。实现游戏积分榜、商品销量排名、热门内容榜单等,通过 ZREVRANGE
快速获取排名靠前的元素。例如:ZADD leaderboard 5000 "player1" 4800 "player2"
。
延迟队列 :将任务的执行时间戳作为 score,使用 ZRANGEBYSCORE
获取到期的任务,实现定时任务调度。通过 ZREM
原子性地取出并删除已处理任务。
范围查询和分段统计 :对学生成绩、商品价格区间、用户年龄分布等进行分段查询和统计,通过 ZRANGEBYSCORE
和 ZCOUNT
实现高效的范围查询。
时间轴系统 :将时间戳作为 score,存储用户动态、新闻事件、系统日志等,通过 ZREVRANGE
获取最新的内容,实现时间序列数据的管理。
带权重的标签和推荐 :存储标签及其权重值,用于热门标签推荐、内容排序等,通过 ZINCRBY
动态调整权重,ZREVRANGE
获取热门项。