压缩列表是 Redis 为了节约内存而开发的。一个压缩列表可以包含任意多个节点, 每个节点可以保存一个字节数组或者一个整数值。
当一个列表键只包含少量列表项, 并且每个列表项要么就是小整数值, 要么就是长度比较短的字符串, 那么 Redis 就会使用压缩列表来做列表键的底层实现。
压缩列表的构成
- zlbytes(uint32_t 类型,4字节):记录整个压缩列表占用的内存字节数。
- zltail(uint32_t 类型,4字节):记录压缩列表表尾节点距离压缩列表的起始地址有多少字节。
- zllen(uint16_t 类型,4字节):记录了压缩列表包含的节点数量。
- entryX(列表节点,长度不定):压缩列表包含的各个节点,节点的长度由节点保存的内容决定。
- zlend(uint8_t 类型,1字节):特殊值0xFF(十进制 255 ),用于标记压缩列表的末端。
压缩列表节点的构成
prevrawlen:以字节为单位, 记录了压缩列表中前一个节点的长度。
- 如果前一个字节的长度小于 254 字节,那么该属性的长度为1字节,保存的值为前一个字节的长度。
- 如果前一个字节的长度大于等于 254 字节,那么该属性的长度为 5 字节,第一个字节的值为0xFE(十进制值 254),而后面的四个字节用于保存前一个字节的长度。
encoding:记录了节点的 content 属性所保存的类型以及长度
- 一字节,两字节或者五字节,值的最高位为 00 、01 或者 10 表示节点的 content 属性保存着字节数组,数组的长度由其他位记录。
- 一字节,值的最高位以 11 开头表示节点的 content 属性保存着整数值,类型和长度由其他位记录。
content:保存节点的值, 节点值可以是一个字节数组或者整数, 值的类型和长度由 encoding 属性决定
- 编码最高位 00 表示字节数组
- 编码后六位 1011 表示长度为11
- 编码最高位 11000000 表示是一个 int16_t 类型的整数值
连锁更新
在一个压缩列表中, 有多个连续的、长度介于 250 字节到 250 字节之间的节点 e1 至 eN。此时如果将一个长度大于等于 254 的新节点 new 放入到 e1 的前置节点位。此时就会发生连锁更新。
压缩列表 API
本文参考《Redis设计与实现》