← 返回首页

redis的zset数据结构

Redis 的 ZSet(Sorted Set,有序集合)是 Redis 中业务价值极高、面试考察最深的数据结构之一。它完美融合了元素唯一、自定义排序、区间检索、排名统计四大能力。

一、 核心定义与特性

ZSet 是一种复合数据结构,其核心由两部分组成:

  • 成员(Member):字符串类型,全局唯一不可重复(与 Set 一致)。
  • 分数(Score):64位双精度浮点数(double),作为元素排序的唯一依据。

独有特性:

  1. 自动有序:默认按 score 从小到大升序排列,支持倒序查询;当多个元素的 score 相同时,会按照 member 的二进制字典序自动排序。
  2. 动态可调序:支持实时增减 score 分数,Redis 会自动刷新元素排序,无需手动重排。
  3. 双重检索维度:既支持按「排名下标」查询,也支持按「分数区间」查询。

二、 底层存储原理

ZSet 是 Redis 优秀的自适应数据结构,会根据数据量大小和元素长度,智能切换底层存储结构以平衡内存与性能:

1. 压缩列表 / Listpack(小数据量场景) 当同时满足以下两个条件时,ZSet 采用内存连续紧凑的结构存储,极大节省内存开销:

  • 集合元素数量 < 128 个。
  • 每个 member 字符串长度 < 64 字节。

2. 跳跃表 + 字典(大数据量场景) 一旦超出上述阈值,ZSet 会自动升级为 Dict(哈希表) + SkipList(跳跃表) 的双结构协同存储:

  • Dict 字典:维护 member -> score 的键值映射。负责快速单点访问,实现 O(1) 时间复杂度查询某个成员的分数或判断其是否存在。
  • SkipList 跳跃表:负责维持全局有序排序、区间范围查询和排名分页。它的多层链表结构使得增删改查及范围操作的时间复杂度均稳定在 O(logN)。

(注:面试高频考点“为什么用跳跃表而不用红黑树?”——因为跳跃表实现更简单、区间查询性能更强、内存开销更低,且更容易在并发环境下实现无锁优化。)

三、 经典应用场景

凭借高效的范围查询和自动排序能力,ZSet 几乎包揽了以下核心业务场景:

  1. 各类排行榜:如直播间贡献榜、游戏战力榜、热搜榜等。将用户 ID 作为 member,点赞数/热度值作为 score,实时更新并秒级刷新榜单。
  2. 延时队列 / 定时任务:将任务 ID 作为 member,执行时间戳作为 score。后台程序通过轮询获取最小时间戳的任务,到点即执行。
  3. 滑动窗口限流:利用 score 存储请求的时间戳,结合范围查询统计特定时间窗口内的请求次数,实现精准限流。
  4. 带权重的共同好友/智能推荐:配合 zinterstore 命令求交集,并按亲密值、互动分做分数加权,重新排序推荐好友。
  5. 时间线列表:如新闻或帖子按发布时间排序,把时间戳当 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 (常用于延时队列消费)