目录
- 1、背景
- 2、压缩列表
- 【1】底层结构
- 【2】特性
- 【3】优缺点
1、背景
ziplist(压缩列表)是redis中一种特殊编码的双向链表数据结构,主要用于存储小型列表和哈希表。它通过紧凑的内存布局和特殊的编码方式来节省内存空间。
2、压缩列表
【1】底层结构
ziplist并不是一个显式的c结构体,而是通过紧凑的字节数组来实现的。它没有传统的struct定义,而是通过内存布局和偏移量来管理数据,其结构如下:
//ziplist整体结构
<zlbytes> <zltail> <zllen> <entry> <entry> ... <entry> <zlend>
字段含义如下:
字段 | 大小(字节) | 说明 |
---|---|---|
zlbytes | 4 | 整个ziplist占用的内存字节数(uint32_t) |
zltail | 4 | 最后一个entry的偏移量(uint32_t) |
zllen | 2 | entry的数量(uint16_t),如果超过2^16-1,需要遍历整个ziplist才能获取准确数量 |
entry | 变长 | 存储的实际数据项 |
zlend | 1 | 固定值0xFF,表示ziplist结束 |
每个entry的存储方式如下:
<prevlen> <encoding> <entry-data>
字段含义如下:
字段 | 大小 | 说明 |
---|---|---|
prevlen | 1或5字节 | 前一个entry的长度(用于方向遍历) |
encoding | 1、2或5字节 | 当前entry的数据类型和长度 |
entry-data | 变长 | 实际存储的数据 |
可以看到encoding和entry-data的长度是可变的,prevlen的编码规则如下:
1、如果前一个entry的长度 < 254字节,则prevlen占用1字节(直接存储长度值)。
2、如果前一个entry的长度 >= 254字节,则prevlen占用5字节(第一个字节是0xFE,后4字节存储实际长度)。
encoding的编码规则如下:
1、如果数据类型为整数,就使用1字节编码。
2、如果数据类型为字符串,就根据字符串长度大小使用1、2、5字节编码。
【2】特性
ziplist的特性如下:
特性 | 描述 |
---|---|
内存紧凑 | 通过特殊编码减少内存使用 |
双向遍历 | 支持从前往后和从后往前遍历 |
变长编码 | 根据数据大小使用不同长度的编码 |
自动升级 | 当数据超过阈值时会自动转换为其它结构 |
连续内存 | 所有数据存储在连续内存块中 |
无指针 | 使用偏移量而非指针,节省空间 |
【3】优缺点
ziplist的优缺点如下:
优点 | 缺点 |
---|---|
内存效率高,节省空间 | 插入/删除操作可能导致连锁更新 |
缓存局部性好 | 查找效率O(n),不适合大数据量 |
减少内存碎片 | 修改操作可能需要重新分配内存 |
适合小数据量存储 | 编码/解码需要额外CPU开销 |
自动转换机制 | 最大长度有限制(默认64KB) |