在早期的 Redis 版本中,数据量较小时使用 ziplist
作为列表的数据结构,数据量较大时则使用 linkedlist
。但考虑到 ziplist
需要频繁的重新分配内存,而 linkedlist
的指针需要额外占用一定的内存(pre 和 next 占据 16 字节),并且由于内存不连续的缘故,更容易产生内存碎片。因此3.2版本之后统一使用 quicklist
作为 列表的数据结构。
结构
quicklist
是 ziplist
和 linkedlist
的一种结合体,中和了两种数据结构的缺点。
快速列表 quicklist
1 | typedef struct quicklist { |
head
、tail
:分别指向头尾quicklistNode
节点count
:所有 ziplist 中 entry 的总和len
:quicklistNode
节点数量fill
:ziplist 的大小设置compress
:压缩深度,0表示不压缩
快速列表节点 quicklistNode
1 | typedef struct quicklistNode { |
prev
、next
:双向链表指针zl
:如果未被压缩,则指向一个 ziplist,如果被压缩的话则指向一个quicklistLZF
结构sz
:ziplist占用多少字节count
:当前 ziplist 存储多少元素encoding
:编码格式:RAW、LZFcontainer
:存储结构,目前只有 ziplist,未来可能会使用其它数据结构
压缩
quicklist
结构体当中有一个 compress
属性:
- 当
compress
取值为0的时候表示不压缩 - 当
compress
取值为n的时候表示两端的 n 个节点不被压缩
由此可见不论 compress
取值为多少,quicklist
的头尾节点都不会被压缩
当一个 quicklistNode
节点需要被压缩时,就会将其 zl
(ziplist) 属性使用 LZF 算法进行压缩,并形成下面的这个结构体
1 | typedef struct quicklistLZF { |
当表list存储大量数据的时候,最容易被访问的很可能是两端的数据,中间的数据被访问的频率比较低(访问起来性能也很低)。如果应用场景符合这个特点,那么list还提供了一个选项,能够把中间的数据节点进行压缩,从而进一步节省内存空间。Redis的配置参数list-compress-depth就是用来完成这个设置的。