有书共读:《Redis设计与实现》第七章和第八章读书笔记
第7章:压缩列表
压缩列表是列表键和哈希键的底层实现之一。
1)当一个列表键只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比较短的字符串,那么Redis就会使用使用压缩列表来做列表键的底层实现。
2)当一个哈希键只包含少量键值对,并且每个键值对的键和值要么就是小整数值,要么就是长度比较短的字符串,那么Redis就会使用压缩列表来做哈希键的底层实现。
压缩列表是Redis为了节约内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含任意多个节点,每个节点可以保存一个字节数组或者一个整数值。
添加新节点到压缩列表,或者从压缩列表中删除节点,可能会引发连锁更新操作,但这种操作出现的几率并不高。
第8章:对象
第8章:对象
Redis使用对象来表示数据库中的键和值,每次当我们在Redis的数据库中新创建一个键值对时,我们至少会创建两个对象,一个对象用作键值对的键(键对象),另一个对象用作键值对的值(值对象)。
对于Redis数据库保存的键值对来说,键总是一个字符串对象,而值则可以是字符串对象、列表对象、哈希对象、集合对象或者有序集合对象中的一种。
1)字符串对象的编码可以是int、raw或者embstr。int编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。embstr编码的字符串对象在执行修改命令之后,总会变成一个raw编码的字符串对象。字符串对象是Redis五种类型的对象中唯一一种会被其他四种对象嵌套的对象。
2) 列表对象的编码可以是ziplist或者linkedlist。ziplist编码的列表对象使用压缩列表作为底层实现,每个压缩列表节点保存了一个列表元素。linkedlist编码的列表对象使用双端链表作为底层实现,每个双端链表节点都保存了一个字符串对象,而每个字符串对象都保存了一个列表元素。当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码:
a)列表对象保存的所有字符串元素的长度都小于64字节;
b)列表对象保存的元素数量小于512个;
不能满足这两个条件的列表对象需要使用linkedlist编码。
3)哈希对象的编码可以是ziplist或者hashtable。ziplist编码的哈希对象使用压缩列表作为底层实现,每当有新的键值对要加入到哈希对象时,程序会先将保存了键的压缩列表节点推入到压缩列表表尾,然后再将保存了值的压缩列表节点推入到压缩列表表尾。hashtable编码的哈希对象使用字典作为底层实现,哈希对象中的每个键值对都使用一个字典键值对来保存。字典的每个键都是一个字符串对象,对象中保存了键值对的键;字典的每个值都是一个字符串对象,对象中保存了键值对的值。当哈希对象可以同时满足以下两个条件时,哈希对象使用ziplist编码:
a)哈希对象保存的所有键值对的键和值的字符串长度都小于64字节;
b)哈希对象保存的键值对数量小于512个;
不能满足这两个条件的哈希对象需要使用hashtable编码。
4)集合对象的编码可以是intset或者hashtable。intset编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合里面。hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象包含了一个集合元素,而字典的值则全部被设置为NULL。当集合对象可以同时满足一下两个条件时,对象使用intset编码:
a)集合对象保存的所有元素都是整数值;
b)集合对象保存的元素数量不超过512个;
不能满足这两个条件的集合对象需要使用hashtable编码。
5)有序集合的编码可以是ziplist或者skiplist。ziplist编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,而第二个元素则保存元素的分值。压缩列表内的集合元素按分值从小到大进行排序,分值较小的元素被放置在靠近表头的位置,而分值较大的元素则被放置在靠近表尾的位置。skiplist编码的有序集合对象使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表。当有序集合对象可以同时满足以下两个条件时,对象使用ziplist编码:
a)有序集合保存的元素数量小于128个;
b)有序集合保存的所有元素成员的长度都小于64字节;
不能满足以上两个条件的有序集合对象将使用skiplist编码。
服务器在执行某些命令之前,会先检查给定键的类型能否执行特定命令,而检查一个键的类型就是检查键的值对象的类型。
Redis的对象系统带有引用计数实现的内存回收机制,当一个对象不再被使用时,该对象所占用的内存就会被自动释放。
Redis会共享值为0到9999的字符串对象。
对象会记录自己的最后一次被访问的时间,这个时间可以用于计算对象的空转时间。