1、Redis 5.0 增加了新的数据结构listpack,它是对ziplist结构的改进,优点是在存储空间上更加节省以及在结构上比ziplist更精简
1)结构体
struct listpack<T> { int32 total_bytes; // 占用的总字节数 int16 size; // 元素个数 T[] entries; // 紧凑排列的元素列表 int8 end; // 同 zlend 一样,恒为 0xFF } |
解析:在结构体上只是比ziplist少了一个zltail_offset字段,该字段是用于定位最后一个元素的位置,用于逆向遍历,而listpack是通过其他方式来定位该位置
2)元数据的结构体
struct lpentry { int<var> encoding; optional byte[] content; int<var> length; } |
解析:同ziplist结构体元素类似,不同点长度字段放在了元素的尾部,而且含义不同了,这里存储的是当前元素的长度,所以可以通过总字节大小(total_bytes)与最后一个字节大小来定位出最后一个元素的位置,另外encoding字段也不同,这里使用varint进行编码,而且元素长度的编码可以是1到5个字节
3)encoding字段设计
0xxxxxxx 表示非负小整数,可以表示0~127。 10xxxxxx 表示小字符串,长度范围是0~63,content字段为字符串的内容。 110xxxxx yyyyyyyy 表示有符号整数,范围是-2048~2047。 1110xxxx yyyyyyyy 表示中等长度的字符串,长度范围是0~4095,content字段为字符串的内容。 11110000 aaaaaaaa bbbbbbbb cccccccc dddddddd 表示大字符串,四个字节表示长度,content字段为字符串内容。 11110001 aaaaaaaa bbbbbbbb 表示 2 字节有符号整数。 11110010 aaaaaaaa bbbbbbbb cccccccc 表示 3 字节有符号整数。 11110011 aaaaaaaa bbbbbbbb cccccccc dddddddd 表示 4 字节有符号整数。 11110011 aaaaaaaa ... hhhhhhhh 表示 8 字节有符号整数。 11111111 表示 listpack 的结束符号,也就是0xFF |
2、级联更新
listpack的设计彻底消灭了ziplist存在的级联更新行为,元素之间完全独立,不会因为某个元素的长度变长就导致后续元素内容受到影响
3、愿景:取代ziplist
listpack设计目的是为了取代ziplist,但是listpack在兼容性方面还存在一些问题而且ziplist使用范围比较广,替换起来比较复杂,所以目前只应用在新增加的数据结构(Stream)中。