Redis 的 ListPack 数据结构是什么?
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
Comments