← 返回首页
redis的zset数据结构
Redis 的 ZSet(Sorted Set,有序集合)是 Redis 中业务价值极高、面试考察最深的数据结构之一。它完美融合了元素唯一、自定义排序、区间检索、排名统计四大能力。
一、 核心定义与特性
ZSet 是一种复合数据结构,其核心由两部分组成:
- 成员(Member):字符串类型,全局唯一不可重复(与 Set 一致)。
- 分数(Score):64位双精度浮点数(double),作为元素排序的唯一依据。
独有特性:
- 自动有序:默认按 score 从小到大升序排列,支持倒序查询;当多个元素的 score 相同时,会按照 member 的二进制字典序自动排序。
- 动态可调序:支持实时增减 score 分数,Redis 会自动刷新元素排序,无需手动重排。
- 双重检索维度:既支持按「排名下标」查询,也支持按「分数区间」查询。
二、 底层存储原理
ZSet 是 Redis 优秀的自适应数据结构,会根据数据量大小和元素长度,智能切换底层存储结构以平衡内存与性能:
1. 压缩列表 / Listpack(小数据量场景) 当同时满足以下两个条件时,ZSet 采用内存连续紧凑的结构存储,极大节省内存开销:
- 集合元素数量 < 128 个。
- 每个 member 字符串长度 < 64 字节。
2. 跳跃表 + 字典(大数据量场景) 一旦超出上述阈值,ZSet 会自动升级为 Dict(哈希表) + SkipList(跳跃表) 的双结构协同存储:
- Dict 字典:维护
member -> score的键值映射。负责快速单点访问,实现 O(1) 时间复杂度查询某个成员的分数或判断其是否存在。 - SkipList 跳跃表:负责维持全局有序排序、区间范围查询和排名分页。它的多层链表结构使得增删改查及范围操作的时间复杂度均稳定在 O(logN)。
(注:面试高频考点“为什么用跳跃表而不用红黑树?”——因为跳跃表实现更简单、区间查询性能更强、内存开销更低,且更容易在并发环境下实现无锁优化。)
三、 经典应用场景
凭借高效的范围查询和自动排序能力,ZSet 几乎包揽了以下核心业务场景:
- 各类排行榜:如直播间贡献榜、游戏战力榜、热搜榜等。将用户 ID 作为 member,点赞数/热度值作为 score,实时更新并秒级刷新榜单。
- 延时队列 / 定时任务:将任务 ID 作为 member,执行时间戳作为 score。后台程序通过轮询获取最小时间戳的任务,到点即执行。
- 滑动窗口限流:利用 score 存储请求的时间戳,结合范围查询统计特定时间窗口内的请求次数,实现精准限流。
- 带权重的共同好友/智能推荐:配合
zinterstore命令求交集,并按亲密值、互动分做分数加权,重新排序推荐好友。 - 时间线列表:如新闻或帖子按发布时间排序,把时间戳当 score,倒序取出即为最新发布列表。
四、 常用高频命令速查
- 添加/更新:
zadd key score member [score member ...](支持 NX/XX 选项控制新增或更新) - 增减分数:
zincrby key increment member - 获取排名:
zrank key member(升序) /zrevrank key member(降序) - 范围查询:
zrange key start stop withscores(按排名) /zrangebyscore key min max(按分数) - 弹出极值:
zpopmin key/zpopmax key(常用于延时队列消费)