[Redis]紧凑列表详解
Redis 5.0 版本又引入了一个新的数据结构 listpack,它是对 ziplist 结构的改进版,在存储空间上会更加节省,而且结构上也比 ziplist 更精简。listpack 的整体形式和 ziplist还是比较接近的,如果你认真阅读了 ziplist 的内部结构分析,那么对于 1istpack 也是比较容易理解的。
struct listpack<T>{
int32 total bytes; // 占用的总字节数
int16 size; // 元素个数
T[]entries; //紧凑排列的元素列表
int8 end; //同zlend 一样,恒为0xFE
}
图 5-15 所示是紧凑列表的内部结构示意图。
首先 listpack 跟 ziplist 的结构几乎一模一样,只是少了一个 zltail offset 字段。ziplist 通过这个字段来定位出最后一个元素的位置,用于逆序遍历,不过 listpack 可以通过其他方式来定位出最后一个元素的位置,所以zltail ofset 字段就被省掉了
struct lpentry{
int<var> encoding;
optional bytel]content;
int<var> length;
listpack 的元素结构和 ziplist 的元素结构也很类似,都是包含三个字段,稍有不同的是,前者的长度字段放在了元素的尾部,而且存储的不是上一个元素的长度,是当前元素的长度。正是因为长度放在了尾部,所以可以省去了用于标记最后一个元素位置的 zltail ofset 字段,最后一个元素的位置可以通过 total bytes 字段和最后一个元素的长度字段计算出来。
listpack 的长度字段使用 varint 进行编码。不同于 skiplist 元素长度的编码只能是1个字节或者5个字节,listpack 元素长度的编码可以是1~5个字节中的任一长度。同 UTF8 编码一样,它通过字节的最高位是否为1来决定编码的长度,如图 5-16 所示。
同样,Redis 为了让 listpack 元素支持很多类型,它对 encoding 字段也进行了较为复杂的设计。
1.0xxxxxxx 表示非负小整数,可以表示 0~127。
2.10xxxxxx 表示小字符串,长度范围是 0~63,content 字段为字符串的内容
3.110xxxxx yyyyyyyy 表示有符号整数,范围是-2048~2047。
4.1110xxxx yyyyyyyy 表示中等长度的字符串,长度范围是 0~4095,content 字段为字符串的内容。
5.11110000 aaaaaaaa bbbbbbbb cccccccc dddddddd 表示大字符串,四个字节表示长度,content字段为字符串内容。
6.11110001 aaaaaaaabbbbbbbb 表示2字节有符号整数
7.11110010 aaaaaaaabbbbbbbb cccccccc 表示3字节有符号整数。
8.11110011 aaaaaaaa bbbbbbbb cccccccc dddddddd 表示4字节有符号整数。
9.11110011aaaaaaaa……hhhhhhhh表示8字节有符号整数。
10.11111111表示 1istpack的结束符号,也就是 0xFF。
5.6.1 级联更新
listpack 的设计彻底消灭了 ziplist 存在的级联更新行为,元素与元素之间完全独立,不会因为一个元素的长度变长就导致后续的元素内容受到影响。
5.6.2 取代 ziplist 尚需时日
listpack 的设计目的是用来取代 ziplist,不过当下还没有做好替换 ziplist 的准备因为仍有很多兼容性的问题需要考虑。ziplist 在 Redis 数据结构中使用得太广泛了替换起来复杂度会非常高。1istpack 目前只使用在新增加的 Stream 数据结构中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?