Skip to content

面试速答(先看这里)

**一句话结论:**在Redis 7.0之前,ZSet主要靠ZipList和 SkipList 实现 。

60秒标准回答:

之所以把他们三个放在一起比较,主要是因为他们都是实现ZSet的主要数据结构

在Redis 7.0之前,ZSet主要靠ZipList和 SkipList 实现 。而在Redis 7.0开始,ZipList已经被ListPack给替代了,也就是说 Redis 7.0之后,ZSet主要靠ListPack和SkipList实现

这里SkipList是一直在的,先介绍他

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **SkipList:**SkipList就是跳表。
  • **ListPack:**ListPack是 Redis 在 5.0 版本引入的一种新的内存高效数据结构(在Redis 7.0正式替代ZipList用在ZSet中),它是为了解决 ziplist 和 skiplist 在一些场景下的不足而提出的。

**记忆锚点:**ZipList → SkipList → ListPack → Redis → ZSet → log

关键取舍:

  • listpack 是一种 适用于小型有序集合、列表和哈希的压缩数据结构 ,它比 ziplist 更加灵活、适应性更强,并且提供了对大数据量的更好支持。

易错提醒:

  • 更重要的事,ListPack通过创新的数据结构方案,避免了级联更新的问题。
  • 而且,因为ZipList的结构导致了,它在极端情况下可能会出现一种级联更新的问题: 所以就有了ListPack ListPack ListPack是 Redis 在 5.0 版本引入的一种新的内存高效数据结构(在Redis 7.0正式替代ZipList用在ZSet中),它是为了解决 ziplist 和 skiplist 在一些场景下的不足而提出的。

加分表达:

  • 但是ZipList也有缺点,正因为他是紧凑的线性结构,所以如果在 ZipList 中查找一个元素时,可能需要遍历整个列表,同理插入和删除操作也是线性的。

追问准备:

  • 围绕「ZipList」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「SkipList」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「ListPack」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

之所以把他们三个放在一起比较,主要是因为他们都是实现ZSet的主要数据结构。

📄 ✅Redis中的Zset是怎么实现的?

打开文档:✅Redis中的Zset是怎么实现的?

在Redis 7.0之前,ZSet主要靠ZipList和SkipList实现。而在Redis 7.0开始,ZipList已经被ListPack给替代了,也就是说Redis 7.0之后,ZSet主要靠ListPack和SkipList实现。

这里SkipList是一直在的,先介绍他。

SkipList ​

SkipList就是跳表。跳表是一种在链表的基础上增加多层索引的结构。跳表的结构通过多层索引链表来提高查找效率,相比于传统的链表,它能够在对数时间内完成元素的查找、插入和删除。

跳表的优势就是插入、删除、查找操作都可以在 O(log N) 的时间复杂度内完成。并且支持高效的范围查询,如 **ZRANGEBYSCORE**、**ZRANGE** 等。

但是跳表有个缺点,那就是他的数据结构决定了他的内存占用更高。每个元素有多个指针来维护多层链表,导致内存开销更大。

ZipList ​

而ZipList是一个压缩的数据结构,它的每个元素都是连续存储的,因此内存的使用非常紧凑。与其他数据结构相比,ZipList在小规模数据存储时显著减少了内存占用。

但是ZipList也有缺点,正因为他是紧凑的线性结构,所以如果在 ZipList 中查找一个元素时,可能需要遍历整个列表,同理插入和删除操作也是线性的。所以ZipList的插入、删除和查找操作的时间复杂度通常是 O(N)。相对来说是比较慢的。

这也是为什么Redis会在元素数量比较少的时候用ZipList,而在数据量大了之后转成SkipList的原因。

📄 ✅ZSet为什么在数据量少的时候用ZipList,而在数据量大的时候转成SkipList?

打开文档:✅ZSet为什么在数据量少的时候用ZipList,而在数据量大的时候转成SkipList?

而且,因为ZipList的结构导致了,它在极端情况下可能会出现一种级联更新的问题:

📄 ✅介绍下Redis中的ZipList和他的级联更新问题

打开文档:✅介绍下Redis中的ZipList和他的级联更新问题

所以就有了ListPack

ListPack ​

ListPack是 Redis 在 5.0 版本引入的一种新的内存高效数据结构(在Redis 7.0正式替代ZipList用在ZSet中),它是为了解决 ziplist 和 skiplist 在一些场景下的不足而提出的。

listpack 是一种 适用于小型有序集合、列表和哈希的压缩数据结构,它比 ziplist 更加灵活、适应性更强,并且提供了对大数据量的更好支持。

更重要的事,ListPack通过创新的数据结构方案,避免了级联更新的问题。

📄 ✅Redis中的ListPack是如何解决级联更新问题的?

打开文档:✅Redis中的ListPack是如何解决级联更新问题的?

对比总结 ​

特性SkipList (跳表)ZipList (压缩列表)ListPack (紧凑列表)
设计目标高效范围查询和有序访问内存紧凑,减少碎片解决级联更新问题
内存布局多层链表结构连续内存块连续内存块
查询复杂度O(log N)O(n)O(n)
插入复杂度O(log N)O(1)~O(n²) (级联更新)O(1) (无级联更新)
删除复杂度O(log N)O(1)~O(n²) (级联更新)O(1) (无级联更新)
内存占用高 (有指针开销)低极低
版本支持所有版本Redis ≤6.2Redis ≥5.0 (7.0+默认)
核心优势高效有序访问小数据内存优化无级联更新+内存紧凑
主要缺点内存占用高级联更新范围查询效率低
应用场景有序集合(ZSet)小规模Hash/Set/ZSet全类型小规模存储