Redis数据结构之list对象

Redis数据结构之list对象

List 对象

一个list对象,可以看到它是quicklist编码。

127.0.0.1:6379> rpush list 1 "hello" 2 3
(integer) 4
127.0.0.1:6379> type list
list
127.0.0.1:6379> object encoding list
"quicklist"

新版本的redis的list对象都是使用quicklit编码。为了更好的理解quicklit编码,我们先介绍quicklit编码的前身,ziplist和linklist。

ziplist和linklist都已经被quicklit所取代,这里只是为了更好的理解quicklit才列出ziplist和linklist两种编码

ziplist编码

顾名思义,压缩链表,为了节约内存空间而设计。

一个压缩链表的结构

Redis数据结构之list对象
·若列表zlbytes属性的值为0x50(十进制80),表示压缩列表的总长为80字节。
·若列表zltail属性的值为0x3c(十进制60),这表示如果我们有一个指向压缩列表起始地址的指针p,那么只要用指针p加上偏移量60,就可以计算出表尾节点entry3的地址。
·若列表zllen属性的值为0x3(十进制3),表示压缩列表包含三个节点。

压缩链表的每一个节点,也就是上图的entry1,entry2结构如下

Redis数据结构之list对象
节点的previous_entry_length属性以字节为单位,记录了压缩列表中前一个节点的长度,也就是说当我们获取到一个指向当前节点的指针p时,么只要用指针p减去偏移量previous_entry_length就可以获得上一个节点,通过zltail属性又可快速获取最后一个节点。压缩链表通过这种方式实现从表尾向表头遍历链表。
压缩链表开辟了一块连续的空间实现了链表结构,极大的提高的内存的利用率,缺点是需要经常要重新分配内存。

ziplist编码的list对象的结构,ptr指向一个压缩链表

Redis数据结构之list对象

linkedlist编码

linkedlist的编码的list对象则是普通的链表结构指向相应的存储对象,图中是指向string对象。

Redis数据结构之list对象
优点是插入新增不需要重新分配内寸,缺点内存使用效率较低。

quicklist编码

了解了ziplist和linkedlist之后就很容易理解quicklist的结构了

quicklist就是每个linkedlist节点都存储一个ziplist对象,每个ziplist为8kb,超过8kb则新建一个节点

Redis数据结构之list对象
这样就极大的降低了内存的碎片化程度,又降低了内存重新分配的规模。

实际使用的时候,quicklist在不断的新增元素时,第一个quicklistNode和最后一个quicklistNode指向的ziplist始终保持不压缩的状态,而中间的ziplist会被再次压缩(执行LZF算法)。不被压缩的ziplist数量是由redis.conf中的list-compress-depth决定的,默认是一,也就是第一个和最后一个不被压缩,当ziplist满了需要新建一个quicklistNode时它的空间限制是8kb,由list-max-ziplist-size决定。

我们可以用rpush,lpush,rpop,lpop等命令操作quicklist。

上一篇:C#-无法退出应用程序


下一篇:Redis学习之ziplist压缩列表源码分析