Redis Zset 的实现原理是什么?
2026/9/17 3:40:25 网站建设 项目流程

Redis ZSet 有序集合实现原理

ZSet =跳表(skiplist) + 哈希表(dict),两套结构同时保存一份数据。

数据特点:成员member唯一不重复,每个member绑定一个分数score,按照score排序。

1. 两个底层结构各自职责

  1. skiplist 跳表
  • 按照score做排序,负责:范围查询、排行榜、倒序、区间分页(zrangezrevrangezrangebyscore
  • Redis的跳表是双向跳表,节点带有back指针,可以高效反向遍历。
  • 平均增删改查 O(log n),最大层数固定32层,节点层数随机生成。
  1. dict 哈希表
  • key:member成员,value:对应的score分数
  • 作用:O(1)时间快速获取某个member的score,判断成员是否存在,保证member唯一性。

插入的时候dict先判断member是否已经存在,实现去重。

⚠️两份结构存的是同一份数据,内存会有少量额外开销,换取查询性能。

2. ziplist 压缩列表(小zset)

当满足两个条件,zset不使用跳表,改用ziplist压缩列表存储:

  1. 元素数量 <zset‑max‑ziplist‑entries默认128
  2. 每个元素大小 <zset‑max‑ziplist‑value默认64字节

ziplist是连续内存,节约内存;内部按score有序排列。
一旦超过阈值,自动转换为 skiplist + dict

3. 核心命令底层怎么走

  • zadd key score member

    1. dict判断member是否存在,存在则更新score;不存在新增
    2. 将数据插入跳表,按score维护有序
  • zscore key member:直接查dict哈希表,O(1)返回分数,不走跳表

  • zrange key start end:直接在skiplist做范围遍历 O(log n + k),k是返回元素数量

4. 业务场景

  • 排行榜、热搜、延时队列、带权重的有序列表

面试常见坑

  1. score可以相同:多个member允许分数一样;score相同会按member字典序排序。
  2. zset没有给member单独过期的能力,只能对整个zset key设置expire。
  3. 不要存超大zset,zrange返回大量数据会阻塞Redis。

总结:
ZSet底层分两种情况,少量短元素用ziplist压缩列表;数据量大则采用跳表+哈希表组合。跳表负责排序和范围查询,哈希表实现快速取score和去重。

口述简短版:
Redis的zset,数据少的时候用压缩列表。数据量大是跳表加上哈希表一起实现。跳表负责按照score排序,用来做排行榜、范围查询;哈希表用来快速拿到成员的分数,保证成员不重复。注意成员唯一,分数可以重复。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询