Redis数据结构之压缩列表ziplist
源码版本:REDIS 5.0.4
ziplist是一个特殊编码的双链表,他被设计出来用以节省内存,它可以同时存储字符串和整整形数,其中整数被编码为实际整数,而不是一系列字符。它可以在O(1)的时间进行头部的插入和尾部的插入,但是他的每次插入都需要进行内存的分配,耗时与表中节点数目有关。
ziplist内存布局
ziplist总体内存布局如下图所示:
zlbytes:无符号32位整形数,它保存了整个ziplist的长度,包括他自身的长度,在增加链表长度的时候不需要遍历整个列表。
zltail:无符号32整形数,它保存了列表中最后一个元素的偏移位置,在列表尾端操作时不需要遍历列表。
zllen:无符号16位短整型数,他保存了链表的个数,当列表中元素个数超过2^16-2 时,
它的值设为2^16-1,此时只有遍历整个列表才知道链表中元素的个数。
zlend:无符号8位的整形数,列表的结尾标识符。
entry:列表中存储的具体元素。
entry结构详解
entry的总体内存布局如下图所示:
当元素存储的是非常小的整数时,数据可以存储在encode当中此时其内存布局如下所示:
prevlen表示列表当中前一个元素的长度,其所占内存可能为1个字节也可能为5个字节,当prev的值为0~253时,它占一个字节的内存,当prev第一个字节的值为254时,它占5个字节的内存。
encode字段决定了存储数据的类型,其具体表示如下分析:
当encode的前两个比特位为00时,encode占一个字节,它最大可以存储63bytes的数据,其长度由6个bit位来存储(|00pppppp|);
当encode的前两个比特位为01时,encode占两个字节,它最大可以存储16383bytes的数据,其长度由14个bit位来存储(|01pppppp|qqqqqqqq|);
当encode的前两个比特位为10时,encode占五个字节,它存储超过16383bytes的数据,最多存储32^2-1bytes的数据,其长度由6个bit位来存储(|10000000|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| );
当encode的前两个比特位为11时,其情况如下:
|11000000|整体占3个字节,其存储 int16_t类型数
|11010000|整体占5个字节,其存储 int32_t类型数
|11100000|整体占9个字节,其存储 int64_t类型数
|11110000|整体占4个字节,其存储 24bit整型数
|11111110|整体占2个字节,其存储 8 bit整型数
|1111xxxx|整体占1个字节,存储1~13的值
|11111111|特殊的列表元素