Redis读书笔记(二)

2023-06-28,

Redis对象系统

Redis对象

字符串(String)的底层实现方式

直接保存整数值:字符串对象保存的是整数值,且可以用long类型来表示。
embstr编码的SDS:字符串对象保存的是一个长度小于等于39字节的字符串值。
SDS:字符串对象保存的是一个长度大于39字节的字符串值。
列表(List)的底层实现方式
压缩列表:列表对象保存的所有字符串元素的长度都小于64字节,且元素数量小于152个(注意:上限值是可以修改的,其他对象的上限值也是同洋的道理)。
双端链表:不满足压缩列表的使用条件,则使用双端链表。
哈希(Hash)的底层实现方式
压缩列表:哈希对象保存的所有键值对的键和值的字符串长度都小于64字节,且键值对数量小于512个。
字典:不满足压缩列表的使用条件,则使用字典。
集合(Set)的底层实现方式
整数集合:集合对象保存的所有元素都是整数,且元素数量不超过512个。
字典:不满足整数集合的使用条件,则使用字典。
有序集合(Zset)的底层实现方式
压缩列表:有序集合保存的元素数量小于128个,且所有元素的长度都小于64字节。
跳跃表+字典:不满足压缩列表的使用条件,则使用跳跃表+字典

Redis对象的实现

typedef struct redisObject {
// 类型
unsigned type:4; // 编码
unsigned encoding:4; // 指向底层数据结构的指针
void *ptr; // 引用计数
int refcount; // 最后一次被命令程序访问的时间
unsigned lru:8; //...
} robj;

对象的类型属性Type

类型常量 对象的名称
REDIS_STRING 字符串对象
REDIS_LIST 列表对象
REDIS_HASH 哈希对象
REDIS_SET 集合对象
REDIS_ZSET 有序集合对象

对象的编码属性Encoding和底层实现

类型 编码 对象
REDIS_STRING REDIS_ENCODING_INT 使用整数值实现的字符串对象
REDIS_STRING REDIS_ENCODING_EMBSTR 使用embstr编码的简单动态字符串实现的字符串对象
REDIS_STRING REDIS_ENCODING_RAW 使用Simple Dynamic String实现的字符串对象
REDIS_LIST REDIS_ENCODING_ZIPLIST 使用压缩列表实现的列表对象
REDIS_LIST REDIS_ENCODING_LINKEDLIST 使用双端链表实现的列表对象
REDIS_HASH REDIS_ENCODING_ZIPLIST 使用压缩列表实现的哈希对象
REDIS_HASH REDIS_ENCODING_HT 使用字典实现的哈希对象
REDIS_SET REDIS_ENCODING_INTSET 使用整数集合实现的集合对象
REDIS_SET REDIS_ENCODING_HT 使用字典实现的集合对象
REDIS_ZSET REDIS_ENCODING_ZIPLIST 使用压缩列表实现的有序集合对象
REDIS_ZSET REDIS_ENCODING_SKIPLIST 使用跳跃表和字典实现的有序集合对象

为什么需要同时使用跳跃表和字典来实现有序集合?

    只使用字典来实现:执行查找的时间复杂度为O(1),但是执行范围性查询操作如ZRANGE、ZRANK等,需要对字典保存的所有元素排序,至少需要O(NlogN)的时间,以及额外的O(N)空间。
    只使用跳跃表来实现:执行范围性查询的优点会被保留,但执行查找的时间复杂度为O(logN)。

所以为了查找和范围性查询都有尽可能快的执行,同时使用字典和跳跃表实现。

内存回收

对象的引用计数会随着对象的使用状态而不断变化:

当创建一个新对象时,引用计数的值被初始化为1
当对象被一个新程序使用时,引用计数的值会加1
当对象不再被一个程序使用时,引用计数的值会减1
当对象的引用计数变为0时,对象所占的内存会被释放

对象共享

Redis中让多个键共享同一个值对象(节约内存):

将key的值指针指向一个现有的对象
将被共享的值对象的引用计数加1

Redis只对包含整数值的字符串对象进行共享

当共享对象时,首先需要检查给定的共享对象和想创建的目标对象是否完全一致,只有在共享对象和目标对象完全相同的情况下才会使用共享对象。

如果共享的是保存整数值的字符串对象,那么验证是否一致的时间复杂度为O(1)
如果共享的是保存字符串的字符串对象,那么验证是否一致的时间复杂度为O(N)
如果共享的是包含了多个值的对象,那么验证是否一致的时间复杂度为O(N*2)

所以考虑到CPU时间的限制,Redis只对包含整数的字符串对象进行共享。

Redis读书笔记(二)的相关教程结束。

《Redis读书笔记(二).doc》

下载本文的Word格式文档,以方便收藏与打印。