Redis 压缩列表(ziplist)内部结构详解

Redis的压缩列表(ziplist)是一种特殊设计的线性数据结构,用于紧凑地存储小尺寸的有序数据序列,尤其适合存储数量较少且元素较小的数据集,例如小型哈希表、集合或有序集合的元素。它在节省内存方面非常有效,因为其内存占用比传统的双向链表更少。

压缩列表(ziplist)的内部结构主要包括以下组件:

  1. Header(头部)
  • zlbytes(4字节):表示压缩列表占用的总字节数。
  • zltail(4字节):记录了从列表头部到达列表尾部(即最后一个entry)的偏移量。
  • zllen(2字节):记录了压缩列表中entry的个数,当entry数量超过2^16-1时,这个值不再准确,需要遍历整个列表来获取确切的entry数量。
  • zlend(1字节):标志压缩列表的结束,其值固定为0xFF。
  1. Entries(节点)
  • 压缩列表的主体由一系列连续的entry组成,每个entry由两个部分构成:previous entry length(前置节点长度)和entry content(节点内容)。
    • Previous Entry Length Encoding(前置节点长度编码):用于记录当前entry前面的entry内容长度,通过变长编码方式节省空间,可以是1字节、2字节或5字节格式。
    • Entry Content(节点内容):存储实际的数据,根据数据类型和大小有不同的编码方式,可以是integers、strings或embstr(嵌入式字符串)等形式。
  1. 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的具体内容结构依其类型和长度而定,可能包含一个或多个字节用于表示长度,然后是实际的数据内容。由于压缩列表是为了节省内存而设计,因此它的内存分配是一块连续的内存区域,便于快速访问和管理。