对象类型
注: 5.0 版本中,前缀 REDIS_ 更改为 OBJ_, 源码位置 src/server.h
3.2 版本 ,新增 quicklist 结构,其用于替换 linkedlist 和 ziplist 结构。
-
结构
typeof struct redisObject { /* 类型 #REDIS_STRING // 字符串 #REDIS_LIST // 列表 #REDIS_SET // 集合 #REDIS_ZSET // 有序集 #REDIS_HASH // 哈希表 */ unsigned type:4; /* 对象编码 #REDIS_ENCODING_RAW // 编码为字符串 #REDIS_ENCODING_INT // 编码为整数 #REDIS_ENCODING_HT // 编码为哈希表 #REDIS_ENCODING_ZIPMAP // 编码为 zipmap #REDIS_ENCODING_LINKEDLIST // 编码为双端链表 #REDIS_ENCODING_ZIPLIST // 编码为压缩列表 #REDIS_ENCODING_INTSET // 编码为整数集合 #REDIS_ENCODING_SKIPLIST // 编码为跳跃表 */ unsigned encoding:4; // 指向底层实现的数据结构指针 void *ptr; // 对象最后一次访问时间, 相对与 server.lruclock 的时间差值,用于内存回收机制 unsigned lru:REDIS_LRU_BITS; // 引用计数,用于内存回收机制 int refcount; } robj;
-
类型和编码
类型 编码 对象 字符串对象 REDIS_STRING REDIS_ENCODING_INT 使用整数值实现的字符串对象 REDIS_STRING REDIS_ENCODING_EMBSTR 使用 embstr 编码的简单动态字符串实现的字符串对象 REDIS_STRING REDIS_ENCODING_RAW 使用简单动态字符串实现的字符串对象 列表对象 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 使用跳跃表和字典实现的有序集合对象
字符串对象
-
编码类型:int、raw、embstr
使用 int 条件:整数值,且可以用 long 来表示
使用 raw 条件 :字符串,长度 > 32 字节
使用 embstr 条件:字符串,长度 <= 32 字节。
注:long double 类型表示的浮点数,在 redis 中是作为 字符串来保存的。 -
raw 和 embstr
内存分配: raw 2 次, embstr 1 次。
内存释放: raw 2 次, embstr 1 次。
embstr 使用连续内存,raw 不是。 -
编码的转换
int 转 raw:对 int 字符串对象进行某些操作后,其结果是字符串值,那么 int 类型转为 raw 类型。
embstr 转 raw :对 embstr 对象执行任意的修改命令时 embstr 转为 raw。 过程 先是将类型转化为 raw,然后执行修改命令。
列表对象
- 编码类型: ziplist、linkedlist
使用 ziplist 条件:
a、字符串长度都小于 64 字节。(list-max-ziplist-value 控制)
b、列表元素数量小于 512 个。 (list-max-ziplist-entries 控制)
以上两个条件都不满足时使用 linkedlist
哈希对象
- 编码类型 ziplist、hashtable
使用 ziplist 作为哈希对象的底层实现时,同一键值对的两个节点紧挨在一起 键在前 值在后。
使用 hashtable 时,键值对都使用一个字典键值对来保存。
使用 ziplist 条件:
a、哈希对象保存的所有键值对的键和值的字符串长度都小于 64 字节。(hash-max-ziplist-value 控制)
b、哈希对象保存的键值对数量小于 512 个。(hash-max-ziplist-entries 控制)
以上两个条件都不满足时使用 hashtable。
集合对象
- 编码类型 intset、hashtable
使用 hashtable 作为集合对象的底层实现时,字典的每个键都是一个字符串对象(保存着一个集合的元素),字典的值都为 NULL。
使用 intset 的条件:
a、集合对象保存的所有元素都是整数值。
b、元素数量不超过 512 个。(set-max-intset-entries 控制)
以上两个条件都不满足时使用 hashtable。
有序集合对象
- 编码类型 ziplist、skiplist
- 使用 ziplist 时,集合元素使用两个紧挨在一起的 ziplist 来保存。 第一个节点保存元素成员(member),第二个节点保存元素的分值(score)。ziplist 中的集合元素按照分值大小排序,较小的放置在靠近表头方向,较大的放置在靠近表尾的方向。
- 使用 skiplist 时,一个 zset 结构用时包含一个字典和一个跳跃表。
跳跃表按分值从小到大保存所有元素。跳跃表节点的 object 保存元素成员(member),节点的 score 属性保存元素的分值。
ZRANK、ZRANGE 命令基于跳跃表 API 实现 - 字典为有序集合创建了从成员到分值的映射,字典中的键值对分别保存元素的成员和分值。
可以通过给定的成员在 O(1) 的时间复杂度中获取成员的分值。 ZSCORE 通过字典特性实现。
字典和跳跃表会使用指针来共享相同的元素和分值,所以不会产生重复的成员或分值,从而浪费额外的内存。
使用 ziplist 的条件:
a、元素数量小于 128 个;(zset-max-ziplist-entries 控制)
b、所有元素成员的长度都小于 64 字节 (zset-max-ziplist-value 控制)
以上两个条件都不满足时使用 skiplist