Redis数据结构之快速列表-quicklist
Posted jeemzz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis数据结构之快速列表-quicklist相关的知识,希望对你有一定的参考价值。
在Redis
的早期版本中,存储list
列表结构时,如果元素少则使用压缩列表ziplist
,否则使用双向链表linkedlist
// 链表节点 struct listNode<T> listNode *prev; listNode *next; T value; listNode; ? // 链表 struct list listNode *head; // 表头指针 listNode *tail; // 表尾指针 long len; // 链表长度 list;
对于链表,有以下特性:
-
双端:节点带有
prev
和next
指针以获取前置、后置节点 -
无环:表头的
prev
和表尾的tail
指向NULL
-
带表头表尾指针:获取表头表尾节点复杂度为
O(1)
-
带链表长度计数器:获取节点数复杂度为
O(1)
-
多态:使用
void*
来保存节点值,可保存不同类型值
快速列表
使用链表的附加空间相对太高,因为64bit
系统中指针是8
个字节,所以prev
和next
指针需要占据16
个字节,且链表节点在内存中单独分配,会加剧内存的碎片化,影响内存管理效率。
考虑到链表的以上缺点,Redis
后续版本对列表数据结构进行改造,使用quicklist
代替了ziplist
和linkedlist
。
// 快速列表节点 struct quicklistNode quicklistNode *prev; quicklistNode *next; ziplist *zl; // 指向压缩列表 int32 size; // ziplist字节总数 int16 count; // ziplist中元素数量 int2 encoding; // 存储形式,表示原生字节数组还是LZF压缩存储 ... quicklistNode; ? // 快速列表 struct quicklist quicklistNode *head; quicklistNode *next; long count; // 元素总数 int nodes; // ziplist节点个数 int compressDepth; // LZF算法压缩深度 quicklist;
从代码可以看出,
quicklist
内部默认单个ziplist
长度为8k
字节,超出这个字节数就会新起一个ziplist
进行存储。
在quicklist
内部,为进一步节约空间,还会使用LZF
算法对ziplist
进行压缩存储。
默认情况下,quicklist
压缩深度为0
即不压缩,实际压缩深度由配置中的list-compress-depth
决定。
为支持快速pop/push
,quicklist
首尾两个ziplist
不进行压缩,此时压缩深度为1
,深度为2
就表示首尾第一个和第二个ziplist
以上是关于Redis数据结构之快速列表-quicklist的主要内容,如果未能解决你的问题,请参考以下文章
5分钟了解Redis的内部实现快速列表(quicklist)