压缩列表是列表键和哈希键底层实现之一。当一个列表键只包含少量列表项,且每个列表项要么是小整数,要么是长度比较短的字符串,Redis就使用压缩列表来做列表键的底层实现。
为节约内存而开发的,由一系列特殊编码的连续内存块组成的顺序型数据结构。
压缩列表的数据结构
struct ziplist<T> {
int32 zlbytes;
// 整个压缩列表占用字节数,进行内存重分配或计算zlend时使用。
int32 zltail;
// 最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点
int16 zllen;
// 元素个数。小于65535时,表示节点数量;大于时,需要遍历才能计算得出。
T[] entry; // 元素内容列表,挨个挨个紧凑存储
int8 zlend; // 标志压缩列表的结束,值恒为 0xFF
}
压缩链表节点的数据结构
每个压缩列表节点可以是一个字节数组,也可以是一个整数。由previous_entry_length,encoding,content组成。
previous_entry_length
单位是字节,记录压缩列表前一个节点的长度。当压缩列表倒着遍历时,需要通过这个字段来快速定位到下一个元素的位置。
当字符串长度小于 254(0xFE) 时,使用一个字节表示;如果达到或超出 254(0xFE) 那就使用 5 个字节来表示。第一个字节是 0xFE(254),剩余四个字节表示字符串长度。
encoding
encoding记录了节点的content属性所保存数据类型和长度。高两位表示存储的是字节数组还是整数。
content
存储节点的值
增加元素
需要重新分配一次内存
连续更新
前面提到每个 entry 都会有一个 prevlen 字段存储前一个 entry 的长度。如果内容小于 254 字节,prevlen 用 1 字节存储,否则就是 5 字节。这意味着如果某个 entry 经过了修改操作从 253 字节变成了 254 字节,那么它的下一个 entry 的 prevlen 字段就要更新,从 1 个字节扩展到 5 个字节;如果这个 entry 的长度本来也是 253 字节,那么后面 entry 的 prevlen 字段还得继续更新。
文章末尾请带上以下文字及链接:本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情