列表对象
概述
ziplist编码的列表对象使用压缩列表作为底层实现,每个压缩列表节点(entry)保存了一个列表元素。
例子如下。如果numbers键的值对象使用的是ziplist编码,这个这个值对对象将会是如图所示的样子。
另一方面,linkedlist编码的列表对象使用双端链表作为底层实现,每个双端链表节点(node)都保存了
一个字符串对象,而每个字符串对象都保存了一个列表元素。
注意,linkedlist编码的列表对象在底层的双端链表结构中包含了多个字符串对象,这种嵌套字符串对象的行为在哈希对象、集合对象、有序集合对象中都会出现,字符串对象是Redis五种类型的对象中唯一一种会被其他四种对象嵌套的对象
例子
- 举个例子,如果执行以下RPUSH命令,那么服务器将创建一个列表对象作为numbers键的值
127.0.0.1:6379> RPUSH numbers 1 "three" 5
(integer) 3
- 举个例子,如果上面的number键创建按的列表对象使用的不是ziplist编码,而是linkedlist编码,
那么numbers键的值对象将会是如图所示
注意
为了简化字符串对象的表示,在上面的图中使用了一个带有StringObject字样的格子来表示
一个字符串对象,而StringObject字样下面的是字符串对象所保存的值。比如说,如图所示的就是
一个包含了字符串值"three"的字符串对象
编码转换
当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码:
- 1.列表对象保存的所有字符串元素的长度都小于64字节
- 2.列表对象保存的元素数量小于512个;
不能满足这两个条件的列表对象需要使用linkedlist编码
对于使用ziplist编码的列表对象来说,当使用ziplist编码所需的两个条件
的任意一个不能被满足时,对象的编码转换操作就会被执行,原本保存在
压缩列表里的所有列表元素都会被转移并保存到双端链表里面,对象的编码,也会从ziplist变为linkedlist
例子
- 举个例子,代码展示了列表对象因为保存了长度太大的元素而进行编码转换的情况
// 所有元素的长度都小于64字节
127.0.0.1:6379> RPUSH blah "hello" "world" "again"
(integer) 3
127.0.0.1:6379> OBJECT ENCODING blah
"ziplist"
// 将一个66字节长的元素推入
127.0.0.1:6379> RPUSH blah "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"
(integer) 4
// 编码已改变
127.0.0.1:6379> OBJECT ENCODING blah
"linkedlist"
// 列表对象包含512个元素
127.0.0.1:6379> EVAL "for i=1, 512 do redis.call('RPUSH', KEYS[1], i) end" 1 "integers"
(nil)
127.0.0.1:6379> LLEN integers
(integer) 512
127.0.0.1:6379> OBJECT ENCODING integers
"ziplist"
// 再向列表对象推入一个新元素,使得对象保存的元素数量达到513个
127.0.0.1:6379> RPUSH integers 513
(integer) 513
// 编码已改变
127.0.0.1:6379> OBJECT ENCODING integers
"linkedlist"
注意:
以上两个条件的上限值时可以修改的,具体看配置文件中关于
list-max-ziplist-value选项和list-max-ziplist-entries选项