quicklist
概述
A doubly linked list of ziplists
根据quicklist.c的注释,这种数据结构是一个以ziplist为节点的双向链表。在redis3.2之后,quicklist取代了压缩列表和linkedlist,成为了列表对象的唯一编码形式。commit 记录
之所以这样设计,是因为原先的linkedlist由于各个节点都是单独的内存,很容易造成内存碎片;而对于压缩列表,由于其每次修改都会引发内存的重新分配,导致大量的内存拷贝。经过对时间和空间的折中,选择了quicklist这种方法。
数据结构
首先来看节点,
1 | typedef struct quicklistNode { |
然后quicklist这个结构体将上面节点表示连起来:
1 | typedef struct quicklist { |
fill的设置与单个quicklistNode的大小有关,当该值为正数时,表示节点指向的ziplist的数据项个数,因此16bit可以最多表示32k的个数;当该值为负数时,表示单个节点最多存储大小。(-1:4kb, -2:8kb, -3:16kb, -4:32kb, -5:64kb)。默认是-2,8kb。
1 |
|
创建
1 | quicklist *quicklistCreate(void) { |
插入push
push操作是通过quicklistpush实现的:
1 | void quicklistPush(quicklist *quicklist, void *value, const size_t sz, |
插入头部的函数,返回0表示已经存在头部,返回1表示创建了新的头部。
1 |
|
检查ziplist的大小是否满足要求
1 |
|
节点压缩
前面提到过,如果当前的节点需要进行压缩,zl数据指针将指向quicklistLZF结构体。
1 | typedef struct quicklistLZF { |
具体的压缩操作函数如下:
1 | /* Compress the ziplist in 'node' and update encoding details. |
具体lzf压缩算法,可以参考lzf_compress函数