← 每日面试题 学习看板

Redis中的Zset是怎么实现的?

面试题/03数据库中间件/02Redis/02数据结构与内部实现/Redis中的Zset是怎么实现的?.md

https://chat.deepseek.com/share/iqv63ua6g2tvbsk7a0


面试记录 2026-10-15

题目:Redis中的Zset是怎么实现的?

难度:medium

评分:⭐⭐⭐⭐☆☆(3/5)

我的回答

redis 中 zset 是有序集合,在底层有两组实现一个是小批量数据的压缩列表,一个是大量数据后的跳跃表;小批量数据到时候,直接按照分数信息进行集合顺序插入到压缩列表中,读取数据的时候遍历压缩列表;当数据量比较大了之后,使用跳跃表实现 zset 有序集合,基于分数构建多层级大跳跃表,每一层级都类似二分的方式去找到下一层级中的一个位置,逐层的快速找到最底层目标数据

点评

优点:

两种底层编码抓到- 跳跃表多层级定位机制描述基本对

不足:

❌ 编码是二选一非递进:ziplist/listpack vs skiplist 是编码切换- ❌ 5.0+ ziplist 已被 listpack 完全替代- ❌ 跳跃表节点还挂哈希表(O(1) member→score)- ❌ 遗漏编码切换阈值:zset-max-listpack-entries=128 / zset-max-listpack-value=64- ⚠️ 跳跃表描述"二分"不准确,是跳级定位不是二分

完整讲解

第一部分:知识重点剖析

核心考点:考察对 Zset 底层编码切换机制的理解,区分"编码二选一"和"递进升级"。

知识点拆解:

  1. Zset 两种编码:
  1. 编码切换阈值(二选一,非递进):
  1. skiplist 结构:
  1. ziplist vs listpack:5.0+ ziplist 已被 listpack 完全替代,性能更好、内存更安全

关键命令复杂度:

第二部分:考察方向与延伸递进

  1. 为什么 Zset 不用 B+ 树?
  1. Zset 编码切换后能回退吗?
  1. Zset 和 SortedSet 接口区别?

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,Zset 有两种底层编码,是二选一关系,不是递进升级。

小数据用 listpack(Redis 5.0+ 替代了 ziplist),连续内存块,内存紧凑。大数据用 skiplist + hashtable 组合。

编码切换阈值是两个:zset-max-listpack-entries(默认 128 个元素)和 zset-max-listpack-value(默认 64 字节)。任一超过就切换到 skiplist。

skiplist 是多层级跳跃表,底层 O(n),顶层 O(1),跳级定位到目标节点。每个节点还挂一个哈希表,通过 member 查找 score 是 O(1)。

ZADD/ZSCORE/ZREMRANGEBYSCORE 在 listpack 上 O(n),在 skiplist 上 O(log n)。ZRANGE 在 skiplist 上 O(log n + m),m 是返回元素数。

编码切换不可逆——一旦切换到 skiplist,即使元素数减少也不会回退 listpack,避免频繁切换的开销。

为什么不用 B+ 树?B+ 树节点大、内存浪费、实现复杂;跳跃表内存紧凑、实现简单、插入删除效率高。Redis 选跳跃表是性能和复杂度的平衡。