压缩列表(ziplist)是列表或字典的底层实现之一。当一个列表只包含少量列表项,并且值的长度较短,或者当一个字典的键值对较少,并且键和值都是较短的字符串,那么Redis就会选择压缩列表作为列表和字典的底层实现
1 | 127.0.0.1:6379> LPUSH list y x d |
压缩列表构成
压缩列表是为了节约内存儿开发的,是由一系列特殊编码的连续内存块组成的顺序性数据结构。一个压缩列表可以包含若干个节点(entry),每个节点可以保存一个字节数组或者一个整数值
上图是压缩列表的构成
属性 | 类型 | 长度 | 用途 |
---|---|---|---|
zlbytes |
uint32_t | 4字节 | 记录整个压缩列表占用的内存字节数,在对压缩列表进行内存分配,或者计算zlend 的位置时使用 |
zltail |
uint32_t | 4字节 | 记录压缩列表尾节点距离压缩列表的起始地址有多少字节。通过这个偏移量,程序可以直接定位尾节点的地址 |
zllen |
uint16_t | 2字节 | 记录了压缩列表包含的节点数量。当这个值小于 65535 时,这个属性的值就是压缩列表包含的节点数量;当这个值等于65535时,需要遍历整个压缩列表才能计算得出 |
entry | 列表节点 | 不定 | 压缩列表包含的各个节点,节点的长度由节点保存的内容决定 |
zlend |
uint8_t | 1字节 | 特殊值 0xFF(十进制255),用于标记压缩列表的末端 |
下图为一个压缩列表的示例:
- 列表属性
zlbytes
值为 0x50(十进制80),表示列表总长为80字节 - 列表属性
zltail
值为 0x3c(十进制60),这表示如果我们有一个起始地址指针 *p,则我们可以直接用这个指针加上zltail
定位到尾节点的地址
压缩列表节点构成
每个压缩列表节点都可以保存一个字节数组或者一个整数,每个节点都有下面三部分组成:
previous_entry_length
:记录了压缩列表中前一个字节的长度。用于定位前一个节点的地址;如果前一节点的长度小于254字节,那么该属性需要用1字节长的空间来保存这个长度值;如果前一节点的长度大于等于254字节,则需要用5字节长的空间来保存这个长度值encoding
:记录了节点的content属性所保存数据的类型以及长度content
:负责保存节点的值,节点值可以是一个字节数组或者整数,值的类型和长度由节点的encoding属性决定。
总结
- 压缩列表是一种为节约内存而开发的顺序型数据结构。
- 压缩列表被用作列表键和哈希键的底层实现之一。
- 压缩列表可以包含多个节点,每个节点可以保存一个字节数组或者整数值。
- 添加新节点到压缩列表,或者从压缩列表中删除节点,可能会引发连锁更新操作,但这种操作出现的几率并不高。