Redis的压缩列表(ziplist)是一种特殊设计的线性数据结构,用于紧凑地存储小尺寸的有序数据序列,尤其适合存储数量较少且元素较小的数据集,例如小型哈希表、集合或有序集合的元素。它在节省内存方面非常有效,因为其内存占用比传统的双向链表更少。
压缩列表(ziplist)的内部结构主要包括以下组件:
- Header(头部):
zlbytes
(4字节):表示压缩列表占用的总字节数。zltail
(4字节):记录了从列表头部到达列表尾部(即最后一个entry)的偏移量。zllen
(2字节):记录了压缩列表中entry的个数,当entry数量超过2^16-1时,这个值不再准确,需要遍历整个列表来获取确切的entry数量。zlend
(1字节):标志压缩列表的结束,其值固定为0xFF。
- Entries(节点):
- 压缩列表的主体由一系列连续的entry组成,每个entry由两个部分构成:previous entry length(前置节点长度)和entry content(节点内容)。
- Previous Entry Length Encoding(前置节点长度编码):用于记录当前entry前面的entry内容长度,通过变长编码方式节省空间,可以是1字节、2字节或5字节格式。
- Entry Content(节点内容):存储实际的数据,根据数据类型和大小有不同的编码方式,可以是integers、strings或embstr(嵌入式字符串)等形式。
- Tail(尾部):
- 压缩列表的尾部是指最后一个entry结束之后的位置,用于后续追加新entry。
当数据量增大到一定程度时,Redis会选择转换为更通用的数据结构,如双向链表(linked list),以维持操作效率。
以下是一个典型的压缩列表内部结构示意:
+------------------+ <- zlbytes
| zlbytes (4 bytes)|
| zltail (4 bytes) |
| zllen (2 bytes) |
+------------------+
| entry 1 |
| entry 2 |
| ... |
| entry N |
+------------------+
| zlend (1 byte) |
+------------------+
每个entry的具体内容结构依其类型和长度而定,可能包含一个或多个字节用于表示长度,然后是实际的数据内容。由于压缩列表是为了节省内存而设计,因此它的内存分配是一块连续的内存区域,便于快速访问和管理。