Redis ziplist(压缩列表)实现详解(基于 6.0.10 版本)
ziplist(压缩列表)是 Redis 为节省内存设计的紧凑数据结构,通过连续内存块存储数据,避免了传统链表的指针开销。它并非通过 “压缩算法” 压缩数据,而是通过紧凑布局减少内存浪费,广泛用于 Hash、List、ZSet 等数据类型的底层实现(当数据量较小时)。
ziplist 核心设计目标
- 节省内存:通过连续内存存储,消除链表节点的指针(prev/next)开销(传统双向链表每个节点需 16 字节指针)。
- 支持双向遍历:通过特殊结构设计,既支持正向遍历,也能高效反向遍历。
- 适配小数据:针对小尺寸元素(如短字符串、整数)优化,不适合存储大型数据或大量元素。
ziplist 整体结构
ziplist 由一系列连续的内存块组成,整体结构如下(单位:字节):
1 | +--------+--------+--------+----------------+----------------+--------+ |
各字段含义:
| 字段名 | 长度(字节) | 作用 |
|---|---|---|
zlbytes |
4 | 记录 ziplist 总字节数(包括自身),用于快速计算内存大小和重分配。 |
zltail |
4 | 记录表尾节点距离 ziplist 起始地址的偏移量(字节),支持快速定位尾节点(无需遍历)。 |
zllen |
2 | 记录节点数量(entry 个数),最大值为 65535(2^16-1)。若超过此值,需遍历整个列表获取真实数量。 |
entry |
可变 | 存储实际数据的节点(每个 entry 结构不同,见下文)。 |
zlend |
1 | 标记列表结尾,固定值为 0xFF(255)。 |
entry 节点结构
每个 entry 是 ziplist 的数据单元,结构如下: