Redis的ZipList、SkipList和ListPack之间的区别

将这三种数据结构放在一起比较,是因为它们都是 Redis 实现 ZSet 的核心数据结构。

在Redis 7.0之前,ZSet 主要采用 ZipList 和 SkipList 两种结构实现。而自Redis 7.0起,ZipList被ListPack取代,因此当前ZSet的核心实现变为ListPack和SkipList。

其中SkipList是长期存在的实现方式,我们先来看它的特性。

SkipList(跳表)

跳表是一种基于链表的多层索引结构,通过在基础链表上增加多级索引来提升查询效率。相比普通链表,跳表能够在 O(log N) 时间复杂度内完成查找、插入和删除操作,并支持高效的范围查询(如 ZRANGEBYSCORE 等命令)。

优势:

  • 所有核心操作(插入/删除/查找)的时间复杂度均为O(log N)
  • 特别适合范围查询场景

不足:

  • 内存占用较高(需要维护多级指针)

ZipList(压缩列表)

ZipList采用连续内存存储方式,所有元素紧密排列,在小数据量时能显著减少内存使用。

优势:

  • 内存利用率极高(紧凑存储)
  • 适合小规模数据存储

不足:

  • 查询、插入和删除都是O(N)时间复杂度
  • 存在级联更新风险

正是由于这些特性差异,Redis 会在元素较少时使用 ZipList,数据量增大后自动转换为 SkipList。

ListPack(紧凑列表)

ListPack 是Redis 5.0引入的新型高效数据结构(7.0+版本正式替代 ZipList ),专为解决 ZipList 和 SkipList 的某些局限性而设计。

特点:

  • 适用于小型有序集合、列表和哈希
  • 比 ZipList 更灵活、适应性更强
  • 完美规避了级联更新问题

对比总结

特性 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)
内存占用 极低
版本支持 全版本 ≤6.2 ≥5.0 (7.0+默认)
核心优势 有序访问高效 小数据内存优化 无级联更新
主要缺点 内存占用高 级联更新 范围查询效率低
适用场景 有序集合(ZSet) 小型Hash/Set/ZSet 全类型小规模存储