Redis 5.0 又引入了一个新的数据结构 listpack,它是对 ziplist 结构的改进,在存储空间上会更加节省,而且结构上也比 ziplist 要精简。它的整体形式和 ziplist 还是比较接近的,如果你认真阅读了 ziplist 的内部结构分析,那么 listpack 也是比较容易理解的。
struct listpack<T> {
int32 total_bytes; // 占用的总字节数
int16 size; // 元素个数
T[] entries; // 紧凑排列的元素列表
int8 end; // 同 zlend 一样,恒为 0xFF
}
首先这个 listpack 跟 ziplist 的结构几乎一摸一样,只是少了一个 zltail_offset 字段。
ziplist 通过这个字段来定位出最后一个元素的位置,用于逆序遍历。不过 listpack 可以通过其它方式来定位出最后一个元素的位置,所以 zltail_offset 字段就省掉了。
struct lpentry {
int<var> encoding;
optional byte[] content;
int<var> length;
}
元素的结构和 ziplist 的元素结构也很类似,都是包含三个字段。不同的是长度字段放在了元素的尾部,而且存储的不是上一个元素的长度,是当前元素的长度。正是因为长度放在了尾部,所以可以省去了 zltail_offset 字段来标记最后一个元素的位置,这个位置可以通过total_bytes 字段和最后一个元素的长度字段计算出来。
长度字段使用 varint 进行编码,不同于 skiplist 元素长度的编码为 1 个字节或者 5 个字节,listpack 元素长度的编码可以是 1、2、3、4、5 个字节。同 UTF8 编码一样,它通过字节的最高为是否为 1 来决定编码的长度。
同样,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 aaaaaaaa bbbbbbbb 表示 2 字节有符号整数。
7、11110010 aaaaaaaa bbbbbbbb cccccccc 表示 3 字节有符号整数。
8、11110011 aaaaaaaa bbbbbbbb cccccccc dddddddd 表示 4 字节有符号整数。
9、11110011 aaaaaaaa ... hhhhhhhh 表示 8 字节有符号整数。
10、11111111 表示 listpack 的结束符号,也就是 0xFF。
级联更新
listpack 的设计彻底消灭了 ziplist 存在的级联更新行为,元素与元素之间完全独立,不会因为一个元素的长度变长就导致后续的元素内容会受到影响。
取代 ziplist
listpack 的设计的目的是用来取代 ziplist,不过当下还没有做好替换 ziplist 的准备,因为有很多兼容性的问题需要考虑,ziplist 在 Redis 数据结构中使用太广泛了,替换起来复杂度会非常之高。它目前只使用在了新增加的 Stream 数据结构中。
思考
为什么 listpack 比 ziplist 更加优秀
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。