Redis底层数据结构之ziplist(压缩列表)
ziplist是Redis中的某些数据类型底层所使用的数据结构Redis中的hash,List,Sorted List这几种类型的数据在某些情况下会使用ziplist来存储。Hash类型当hash类型的数据满足以下条件时,底层使用ziplist存储。当hash键值对个数小于等于 hash-max-ziplist-entries 配置的值,默认512当键值对中值的长度小于等于 hash-max-zi
ziplist是Redis中的某些数据类型底层所使用的数据结构
Redis中的hash,List,Sorted List这几种类型的数据在某些情况下会使用ziplist来存储。
Hash类型
当hash类型的数据满足以下条件时,底层使用ziplist存储。
- 当hash键值对个数小于等于 hash-max-ziplist-entries 配置的值,默认512
- 当键值对中值的长度小于等于 hash-max-ziplist-value 配置的值,默认64
当hash类型的数据同时满足以上两个条件时,会将value采用ziplist来存储。
List类型
redis中list类型的数据底层是使用quicklist来存储的,而quicklist是基于linkedlist + ziplist实现的。
Sorted Set类型
当Sorted Set类型的数据满足以下条件时,底层使用ziplist存储。
- 当元素个数小于等于 zset-max-ziplist-entries配置的值,默认128
- 每个元素的值小于等于 zset-max-ziplist-value配置
当Sorted Set类型的数据同时满足以上两个条件时,会将value采用ziplist来存储。
ziplist的内存布局
ziplist是由一系列特殊编码的连续内存块组成的顺序存储结构,类似于数组,ziplist在内存中是连续存储的,但是不同于数组,为了节省内存 ziplist的每个元素所占的内存大小可以不同,每个节点可以用来存储一个整数或者一个字符串。
ziplist类似于双向链表,但是它不存储上一个节点和下一个节点的指针,而是存储上一个节点长度和当前节点长度,通过牺牲部分读写性能,来换取高效的内存空间利用率,节约内存。
-
zlbytes:记录了压缩列表占用的内存字节数,在对压缩列表进行内存重分配,或者计算zlend的位置时使用。它本身占了4个字节。
-
zltail:记录了尾节点(entry)至起始节点(entry)的偏移量。通过这个偏移量,可以快速确定最后一个entry节点的地址。
-
zllen:记录了entry节点的数量。当zllen的值小于65535时,这个值就表示节点的数量。当zllen的值大于65535时,节点的真实数量需要遍历整个压缩列表才能得出。
-
entry:压缩列表中所包含的每个节点。每个节点的长度根据该节点的内容来决定。
-
zlend:特殊值0XFF,标记了压缩列表的末端。表示该压缩列表到此为止。
值得注意的是,这个压缩列表的内存空间是连续的。这也是压缩列表的主要特点,空间连续,避免内存碎片,节省内存。
entry是链表中的一个节点,代表了一个数据。
redis中对压缩列表中节点的定义如下:
typedef struct zlentry {
unsigned int prevrawlensize; /*存储上一个节点长度的数值所需要的字节数*/
unsigned int prevrawlen; /* 上一个节点的长度 */
unsigned int lensize; /* 当前节点长度的数值所需要的字节数*/
unsigned int len; /* 当前节点的长度 */
unsigned int headersize; /* 当前节点的头部大小,值 = prevrawlensize + lensize. */
unsigned char encoding; /* 编码方式,ZIP_STR_* 或 ZIP_INT_* */
unsigned char *p; /* 指向节点内容的指针. */
} zlentry;
虽然定义了这个结构体,但是根本就没有使用zlentry结构来作为压缩列表中用来存储数据节点中的结构,因为,这个结构存小整数或短字符串实在是太浪费空间了。这个结构总共在32位机占用了28个字节(32位机),在64位机占用了32个字节。这不符合压缩列表的设计目的:提高内存的利用率。因此,在redis中,并没有定义结构体来进行操作,而是定义了一些宏,压缩列表的节点真正的结构如下图所示:
- prev_entry_len:记录前驱节点的长度。
- encoding:记录当前节点的value成员的数据类型以及长度。
- value:根据encoding来保存字节数组或整数。
具体的含义,要深入理解的话,参考:ziplist源码剖析
ziplist的特点
- 压缩列表ziplist结构本身就是一个连续的内存块,由表头、若干个entry节点和压缩列表尾部标识符zlend组成,通过一系列编码规则,提高内存的利用率,使用于存储整数和短字符串。
- 压缩列表ziplist结构的缺点是:每次插入或删除一个元素时,都需要进行频繁的进行内存的扩展或减小,然后进行数据”搬移”,甚至可能引发连锁更新,造成严重效率的损失。
更多推荐
所有评论(0)