遵循文档,其实我在想为什么文档里要详细介绍对象的编码这个东西呢?能否有人知道有啥用,我们业务型程序员关注不到这些东西,都是只是会使用。
列表的编码有两个,ziplist和linkedlist,看名字就能知道,估计一个是存大量的数据,一个存少量的,瞎猜的,,,
1. ziplist,可见一般少量的数据,应该就是使用的ziplist
127.0.0.1:6379> lpush nlist 1 "one"
(integer) 2
127.0.0.1:6379> object encoding nlist
"ziplist"
127.0.0.1:6379>
结构如下,直接搬过来,可见对于列表数据,是有一个另外的数据结构,以后去研究下,现在知道,知道就行
但是假想一下,如果编码不是ziplist,而是linkedlist呢?那么书中也画出来了,如下:其实之前看过javamap的源码,linkedlist中存放数据时,其实是一个一个的entry链接起来的,这边也是一样,但是需要注意这边把字符串对象嵌套进来了,这也是redis中字符串是唯一一个会被其他几种类型对象嵌套进入的,
此处需要注意下的是简化版的StringObject对象,其实在上一篇里面有记载:如果是小一点的字符串对象,那么是连续的空间,如果不是的话,应该就是两个空间
当然,书里也介绍了编码的转换,
使用ziplist的条件:
1. 列表对象保存的所有字符串元素的长度小于64字节
2. 列表对象保存的元素数量小于512个
不满足的使用linkedlist。
但是第二篇里面关于配置文件的,我记得是有两个配置项是设计到这个的list-max-ziplist-value 选项和 list-max-ziplist-entries。这个要注意一下,可以实践体会下。
稍微加点东西进去,能够改变编码方式
127.0.0.1:6379> rpush nlist "ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
(integer) 5
127.0.0.1:6379> object encoding nlist
"linkedlist"
127.0.0.1:6379>
以下为列表方式 的部分实现,这个的话应该跟源码相关了,在此只是记录
命令 | ziplist 编码的实现方法 | linkedlist 编码的实现方法 |
---|---|---|
LPUSH | 调用 ziplistPush 函数, 将新元素推入到压缩列表的表头。 | 调用 listAddNodeHead 函数, 将新元素推入到双端链表的表头。 |
RPUSH | 调用 ziplistPush 函数, 将新元素推入到压缩列表的表尾。 | 调用 listAddNodeTail 函数, 将新元素推入到双端链表的表尾。 |
LPOP | 调用 ziplistIndex 函数定位压缩列表的表头节点, 在向用户返回节点所保存的元素之后, 调用ziplistDelete 函数删除表头节点。 | 调用 listFirst 函数定位双端链表的表头节点, 在向用户返回节点所保存的元素之后, 调用 listDelNode 函数删除表头节点。 |
RPOP | 调用 ziplistIndex 函数定位压缩列表的表尾节点, 在向用户返回节点所保存的元素之后, 调用ziplistDelete 函数删除表尾节点。 | 调用 listLast 函数定位双端链表的表尾节点, 在向用户返回节点所保存的元素之后, 调用 listDelNode 函数删除表尾节点。 |
LINDEX | 调用 ziplistIndex 函数定位压缩列表中的指定节点, 然后返回节点所保存的元素。 | 调用 listIndex 函数定位双端链表中的指定节点, 然后返回节点所保存的元素。 |
LLEN | 调用 ziplistLen 函数返回压缩列表的长度。 | 调用 listLength 函数返回双端链表的长度。 |
LINSERT | 插入新节点到压缩列表的表头或者表尾时, 使用ziplistPush 函数; 插入新节点到压缩列表的其他位置时, 使用 ziplistInsert 函数。 | 调用 listInsertNode 函数, 将新节点插入到双端链表的指定位置。 |
LREM | 遍历压缩列表节点, 并调用 ziplistDelete 函数删除包含了给定元素的节点。 | 遍历双端链表节点, 并调用 listDelNode 函数删除包含了给定元素的节点。 |
LTRIM | 调用 ziplistDeleteRange 函数, 删除压缩列表中所有不在指定索引范围内的节点。 | 遍历双端链表节点, 并调用 listDelNode 函数删除链表中所有不在指定索引范围内的节点。 |
LSET | 调用 ziplistDelete 函数, 先删除压缩列表指定索引上的现有节点, 然后调用 ziplistInsert 函数, 将一个包含给定元素的新节点插入到相同索引上面。 | 调用 listIndex 函数, 定位到双端链表指定索引上的节点, 然后通过赋值操作更新节点的值。 |