ziplist 是 Redis 中一种紧凑型的列表结构,专门用来存储元素数量少且每个元素较小的数据。它是一个双端链表, 可以在任意一端进行压入/弹出操作,并且该操作的时间复杂度为O(1)。
字段 | 字节数 | 描述 |
---|---|---|
zlbytes | 4 字节 | 记录整个 ziplist 所占用的字节数 |
zltail | 4 字节 | 记录 ziplist 最后一个元素的偏移量 |
zllen | 2 字节 | 记录 ziplist 中包含的元素个数(最大为 65535) |
entryX | 不定长 | 每个元素的数据,包括 prevlen、encoding 和 content |
zlend | 1 字节 | 特殊值 0xFF,标志 ziplist 的结束 |
字段 | 字节数 | 描述 |
---|---|---|
prevlen | 1 或 5 字节 | 记录前一个元素的长度,为了方便反向遍历ziplist |
encoding | 1-5 字节 | 记录当前元素的类型和长度信息 |
content | 不定长 | 具体的数据内容,长度由 encoding 部分决定 |
虽然ziplist对头尾的操作可以很快,但是,当要查找列表中间的元素时,ziplist 就得从列表头或列表尾遍历才行。而当 ziplist 保存的元素过多时,查找中间数据的复杂度就会增加。因此,ziplist的最大存储元素数量和每个元素的大小直接影响其性能。
在Redis.conf
文件中有默认配置:
# 最大元素个数
hash-max-ziplist-entries 512
# 元素最大字节数
hash-max-ziplist-value 64
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
由于ziplist 必须使用一块连续的内存空间来保存数据,所以当新插入一个元素时,ziplist 就需要计算其所需的空间大小,并申请相应的内存空间,假设有N个小于255字节的Entry,每一个Entry的pre_entry_len
都可以用1个字节存储,现在要在中间插入新的Entry,长度大于254,此时pre_entry_len
就需要5字节来存,后续的元素的prevlen
字段也需要扩展,就会引起连锁更新的问题。这一系列操作,可以从 ziplist 的元素插入函数__ziplistInsert
中看到。
到这里结束,希望本文对你有帮助。