Listpack
为什么需要 listpack,listpack 解决了什么问题?
Listpack 可以说是用来替代 ziplist 的,zipList 是一种特殊的双向链表(不使用指针来找到它前一个或者后一个元素),它的 entry 是使用 prebious_entry_length
记录前一个节点的长度,从而实现从后往前遍历,使用 encoding
来记录当前节点的数据类型和长度,从而知道当前节点的长度,实现从前往后遍历。因为使用prebious_entry_length
记录前一个节点的长度,因此它有连锁更新
的问题
在 Listpack 中,每一个 entry 只记录自己的长度,因此在新增或者修改元素时,只会涉及当前 entry 的更新,而不会影响到别的
Listpack 的 entry 的结构
为了节省内存,有一些小的数字/字符串会直接存储在 encoding-type 中,不会使用 element-data 存储
encoding-type:变长的字段,其主要的作用就是记录数据的类型以及数据的长度,具体可以看官方文档
element-data:存储数据
element-tot-len:表示 entry 的大小(即 encoding-type 和 element-data 的长度),用于从后往前遍历。
该变量是可变长的,如果 entry 比较小,可能
element-tot-len
只使用 1B,如果 entry 比较大,就会逐渐增加字节数该字段是从右往左解析的,例如 element-tot-len 为 0000011 1110100 ,则从最后面的 0 开始解析。
每个字节第一个 bit 表示是否结束,0 表示结束,1 表示没结束,因此只有 7bit 真正有用
例如需要存储长度为 500 的 entry,500 的二进制 111110100
因此 element-tot-len 为: 0000011 1110100
Listpack 如何进行遍历
从左往右遍历
根据encoding-type
可以知道 encoding-type 和 element-data 的总字节数,从而可以计算出 element-tot-len 的字节数,因此可以得到当前整个 entry 的字节数,从而找到下一个 entry
1 |
|
从右往左遍历
我们通过对上一个元素的 element-tot-len 的每个字节,从而可以得到 element-tot-len 占用的字节数 以及根据 element-tot-len 的内容可以得到 encoding-type 和 element-data 的字节数,从而完成从右往左遍历
1 |
|
巨人的肩膀
深入分析 redis 之 listpack,取代 ziplist?
- 本文作者: leftover
- 版权声明: 本文版权归leftover所有,如需转载清标明来源!