redis源码学习–数据结构:ziplist设计

ziplist的重点在于压缩,为了高效使用内存,需要对数据结构进行压缩。链表结构理论上需要有额外的空间存储指针字段,所以ziplist实际上用的是连续内存。

下面介绍ziplist的结构

字段

长度

解释

zlbytes

占4个字节

表示整块结构的长度,包含自己

zltail

占4个字节

从头到最后一个元素的偏移地址,可以方便的从后遍历

zllen

占2个字节

表示元素的个数,可以超过全F表示超过了65535,数量需要自己从大头到尾数

entry

不确定

元素1

entry

不确定

元素2


还是元素

entry

不确定

最后一个元素

zlend

占用1个字节

结束符,固定255

entry的结构如下:

字段

长度

解释

prevlen

占1个字节或者5个字节

表示前一个entry占用的字节数,长度小于254(0xFE)用1个字节表示,否则用5个字节。当使用5个字节表示时,第一个字节固定为0xFE,用其余的4个字节表示长度。

encoding

不确定

表示编码格式,第一个字节的高两bit用来区分数据内容是string还是int。11表示是int,否则都是string

entry-data

不确定

表示编码后的值

下面详细说明encoding:

高bit

类型

占用长度

解释

00

string

1个字节

string长度用剩下的6bit,长度使用的是大端序,下同

01

string

2个字节

string长度用剩下的14bit

10

string

5个字节

string长度用剩下的32bit

11000000

16位int

4个字节

编码使用1字节,数值占用3字节

11010000

32位int

5个字节

编码使用1字节,数值占用4字节

11100000

64位int

9个字节

编码使用1字节,数值占用8字节

11110000

24位int

3个字节

编码使用1字节,数值占用3字节

11111110

8位int

2个字节

编码使用1字节,数值占用1字节

1111XXXX

4位int

1个字节

编码和数值共占1位,XXXX表示具体的数据,范围0到12。使用0001表示数值0,1101表示数据12。由于末尾结束符为11111111,所以1111不能被使用。11110000和11111110都有含义,所以只能表示0到12.

下面这个例子应该比较容易看懂

[0f 00 00 00]

[0c 00 00 00]

[02 00]

[00 f3]

[02 f6]

[ff]

zlbytes 总占内存15字节

zltail 偏移12

entries 元素数量2

int 2

int 5

end

下面的例子是在int 5之后插入一个字符串“hello world”(不包含结束符)的entry的内存结构

02

0b

48 65 6c 6c 6f 20 57 6f 72 6c 64

前一个元素是2字节长度

高位为00,所以低6位表示字符串长度,b表示11个字节

分别是每个字母的ASCII码

整个zlbytes的码流:

[1c 00 00 00]

[0e 00 00 00]

[03 00]

[00 f3]

[02 f6]

[02 0b 48 65 6c 6c 6f 20 57 6f 72 6c 64]

[ff]

zlbytes 总占内存28字节

zltail 偏移14

entries 元素数量3

int 2

int 5

hello world

end

至此,我们已经学完了ziplist的编码原理和数据结构的设计,下一篇我们继续学习其代码实现。