【笔记】《Redis设计与实现》chapter8 对象
8.1 对象的类型与编码
Redis中的每个对象都由一个redisObject结构表示,该结构中和保存数据有关的三个属性分别是type属性、encoding属性和ptr属性
typedef struct redisObject{
// 类型
unsigned type:4;
// 编码
unsigned encoding:4;
// 指向底层实现数据结构指针
void *ptr;
// ...
}robj;
类型
编码和底层实现
通过encoding属性来设定对象所使用的编码,而不是为特定类型的对象关联一定的编码,极大地提升了Redis的灵活性和效率,因为Redis可以根据不用的使用场景来为一个对象设置不同的编码,从而优化对象在某一场景下的效率
8.2 字符串对象
如果字符串对象保存的是一个字符串值,并且字符串值的长度大于39字节,那么字符串对象将使用简单动态字符串来保存这个字符串值
编码的转换
因为Redis没有为embstr编码的字符串编写任何的修改程序,所以对embstr编码的字符串对象实际上是只读的,当我们对embstr编码的字符串对象执行任何修改命令时,程序会先将对象的编码从embstr转换成raw,然后执行修改命令
字符串命令的实现
8.3 列表对象
编码转换
当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码
-
列表对象的所有字符串元素的长度都效于64字节
-
列表对象保存的元素数量小于512个;
不能满足这两个条件的列表对象需要使用linkedlist编码
8.4 哈希对象
哈希对象的编码可以是ziplist 或者 hashtable
ziplist编码的哈希对象
hashtable编码的哈希对象
编码转换
当哈希对象可以同时满足一下两个条件时,哈希对象使用ziplist编码
- 哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
- 哈希对象保存的键值对数量小于512个
不能满足这两个条件的哈希对象需要使用hashtable编码
哈希命令的实现
8.5 集合对象
集合对象的编码可以是intset 或者 hashtable
intset编码集合对象
hashtable编码集合对象
编码的转换
当集合对象可以同时满足一下两个条件时,对象使用intset编码:
-
集合对象保存的所有都是整数值
-
集合对象保存的元素数量不超过512个
当集合对象可以同时满足以下两个条件时,对象使用inteset编码
8.4 有序集合对象
有序集合的编码可以时ziplist 或者 skiplist
ziplist编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存
压缩列表内的集合元数按分支从小到大进行排序
编码的转换
当有序集合对象可以同时满足以下两个条件时,对象使用ziplist编码
- 有序集合保存的元素数量小于128个
- 有序集合保存的所有元素成员的长度都小于64字节
不能满足以上两个条件的有序集合集合将使用skiplist编码
有序集合命令的实现
8.7 类型检查与命令多态
多态命令的实现
我们可以将DEL、EXPIRE、TYPE等命令也称为多态命令,因为无论输入的键是什么类型,这些命令都可以正确地执行
8.8 内存回收
通过引用计数机制实现内存回收
typedef struct redisObject{
//...
// 引用计数
int refcount;
//...
}
8.9 对象共享
不共享包含字符串的对象,性能消耗高