“redis有序集合,内部有2种实现方式,一种为压缩链表,另一种为跳跃表。两者都是redis的基本数据结构,各有千秋。今天我们通过zet的来深入的认识下他们。”
01
—
压缩列表ziplist
由一系列连续的内存块组成的顺序型数据结构,通过连续分配内存的方式,可以节约内存。通过复杂的设计,来最大化节省内存。
结构
zlbytes + zltail + zllen+ entry1 + entry2 + ... + zlend
其中:
zlbytes:压缩列表总字节数,占4个字节
zltail:尾结点的偏移量,占4个字节
zllen:列表中结点的个数,占2个字节
entry1:结点(下文会详细说明)
zlend:固定为0xFF
可知:头部位置为从zl偏移10个字节就拿到第一个entry的地址。即p = zl + 10 ,尾部位置就是 p = zl + zltail代表的offset
entry的实际构成:prevlen + encoding + entry-data 或者 prevlen + encoding
(注意:这里的构成和ziplist.c中struct zlentry不同)
prevlen:前一个结点的字节数,prevlen字段可能占1个字节,也可能占5个字节,当占一个字节数时,代表前一个entry的总字节数不超过254。当占5个字节数时,前一个entry的所占的总字节数为5个中的后四个字节所表示的数,比如 0xfe 00 00 00 ff 代表前一个entry总字节数为255个字节。
encoding:本结点的编码,这里的编码中也包含了本节点的entry-data字节长度。
字符类型的编码:
ZIP_STR_06B:(0 << 6) 即00xxxxxx 前两位00表示最大长度为63的字符串,后面6位表示实际字符串长度,encoding占1个字节
ZIP_STR_14B (1 << 6) 即01xxxxxx xxxxxxxx 前两位01表示中等长度的字符串(63
ZIP_STR_32B (2 << 6) //10000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 特大字符,第一个字节固定128(0X80),后面四个字节存储实际长度,encoding占用5个字节
int类型的编码:统一占一个字节
ZIP_INT_16B (0xc0 | 0<<4) //11000000 content内容是int16,长度是2个字节
ZIP_INT_32B (0xc0 | 1<<4) //11010000 content内容是int32,长度是4个字节
ZIP_INT_64B (0xc0 | 2<<4) //11100000 表示content内容是int64,长度是8个字节