Redis 的 ListPack 数据结构是什么?

Sherwin.Wei Lv7

Redis 的 ListPack 数据结构是什么?

回答重点

ListPack 是 Redis 内部的一种数据结构,用于高效存储短小的字符串或整数集合。它是一种紧凑型的序列化数据结构,旨在减少内存占用和提升性能。为了尽可能紧凑地存储数据,因此它没有使用 Redis 常见的对象模型,而是直接以字节序列的形式存储数据。

ListPack 是 Redis 6.0 引入的新数据类型,在 List、Hash 和 ZSet 的内部实现中使用。

ListPack 的优点:

  • 内存高效:通过变长编码和紧凑存储减少内存占用。
  • 高性能:由于数据紧凑存储,可以更快地进行读取和写入操作。
  • 简单实现:结构简单,便于实现和维护。

扩展知识

为什么引入了 ListPack

很多人对 ListPack 比较陌生,它其实是用来替代 ziplist 的。

在 ListPack 中,Redis 作者描述了下面这段话:

因为发现了一个 bug,怀疑了 ziplist 连锁更新导致的,所以就设计了 ListPack。

它采用一种紧凑的格式来存储多个元素(本质上仍是一个字节数组),并且使用多种编码方式来表示不同长度的数据。

  • header:整个 listpack 的元数据,包括总长度和总元素个数。
  • elements:实际存储的元素,每个元素包括长度和数据部分。
  • end:标识 listpack 结束的特殊字节。

element 的内部结构如下:

  • encoding-type:元素的编码类型。
  • element-data:实际存放的数据。
  • element-tot-len:encoding-type + element-data 的总长度,不包含自己的长度。

之所以设计它来替换 ziplist 就是因为 ziplist 连锁更新的问题,因为 ziplist 的每个 entry 会记录之前的 entry 长度

如果前面的 entry 长度变大,那么当前 entry 记录前面 entry 的字段所需的空间也需要扩大,而当前的变大了,可能后面的 entry 也得变大,这就是所谓的连锁更新,比较影响性能。

而 ListPack 的每个元素,仅记录自己的长度,这样一来修改会新增不会影响后面的长度变大,也就避免了连锁更新的问题。

Ziplist 和 Quicklist

Redis 的 Ziplist 和 Quicklist

Comments