数据结构-Ziplist
ziplist
是 Redis 中的一种紧凑型、压缩型、双向链表结构。
在 ziplist
中,每个节点 entry
由两部分字段组成:头部信息和数据信息。
头部信息包括节点的长度、前一个节点的长度和节点的类型
数据信息指向实际的数据。
结构
虽然 redis 定义了节点 zlentry 结构体,但却没有用 zlentry
结构来存储节点。因为这个结构存小整数或短字符串太浪费空间,不符合压缩列表提高内存利用率的设计目的,因此,在 redis 中,并没有使用 zlentry
结构,而是定义了宏来表示压缩列表的节点。 entry
的实际结构如下:
previous_entry_length
:前一个节点的长度,占 1Byte
或 5Byte
如果前一个节点的长度小于
254Byte
,则需要1Byte
来保存前一个节点的长度如果前一个节点的长度
>= 254Byte
,则需要5Byte
来保存前一个节点的长度,第一个Byte
固定为0xfe(254)
,后四个Byte
表示前一个节点的长度。用254
不用255(11111111)
作为分界是因为255
是zlend
的值,它用于判断ziplist
是否到达尾部。
encoding
编码的设计较为复杂,这里简单写下。对于 encoding
的前两位:
11
表示为整数00
表示为字符串整数节点
encoding
永远是8
位,字符串节点的encoding
可以有8
位、16
位、40
位三种长度
所以在 ziplit.c
里可以看到大量如下的代码:
ziplist
用在 Zset
和 Quicklist
中。使用时的结构是这样的:
插入/删除元素
向中部插入/删除某个节点时,需要更新
next
节点的pre_entry_length
next
节点的pre_entry_length
变长或变短可能又导致节点本身长度改变,进而导致next.next.pre_entry_length
需要变更这就是说, 在某个/某些节点的前面添加新节点之后, 程序必须沿着路径挨个检查后续的节点,是否满足新长度的编码要求
不过,因为只有在新添加节点的后面有连续多个长度接近
254
的节点时,这种连锁更新才会发生, 所以可以普遍地认为,这种连锁更新发生的概率非常小
Last updated