对象的类型与编码
redis使用对象来表示数据库中的键和值,每次当我们在redis的数据库中新创建一个键值对时,我们至少会创建两个对象,一个对象用作键值对的键(键对象),另一个对象用作键值对的值(值对象)。
redis中美国对象都由redisObject结构表示:
typedef struct redisObject{
//类型
unsigned type:4;
//编码
unsigned encoding:4;
//指向底层实现数据结构的指针
void *ptr;
}
类型(type):
对象的type属性记录了对象的类型,这个属性可以是以下表中其中一个。
类型常量 | 对象的名称 |
---|---|
REDIS_STRING | 字符串对象 |
REDIS_LIST | 列表对象 |
REDIS_HASH | 哈希对象 |
REDIS_SET | 集合对象 |
REDIS_ZSET | 有序集合对象 |
编码(encoding):
相同的类型(type)会对应不同的编码,且不同编码其含义也不一样,之后会一一介绍。
字符串对象
字符串对象的编码(encoding)可以是int、raw或embstr。
如果一个字符串对象保存的是整数值,并且这个整数值可以用long类型来表示,那么次字符串的编码(encoding)为int
如果字符串对象保存的是一个字符串值,并且这个字符串值的长度大于39字节,那么字符串对象使用简单动态字符串(SDS)来保存,并将编码(encoding)设置为raw。
如果字符串对象保存的是一个字符串值,并且这个字符串值的长度小于等于39字节,那么编码(encoding)为embstr。
编码转换:
int编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。
比如:int类型转换为长度大于39字节,并且不是long类型的字符串。
列表对象
列表对象可以是ziplist或者linkedlist
ziplist编码的列表对象使用压缩列表作为底层实现,每个压缩列表节点(entry)保存了一个列表元素。
linkedlist编码的列表对象使用双端链表作为底层实现。
编码转换:
当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码:
列表对象保存的所有字符串元素的长度都小于64字节。
列表对象保存的元素数量小于512个;
若不能满足则使用linkedlist。
哈希对象
哈希对象可以是ziplist或者hashtable
ziplist编码的列表对象使用压缩列表作为底层实现,每两个压缩列表节点(entry)保存了一个为键一个为值的字符串对象。
hashtable编码使用字典作为底层实现,哈希对象中的每个键值对都使用一个字典键值对来保存。
编码转换:
当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码:
列表对象保存的所有字符串元素的长度都小于64字节。
列表对象保存的元素数量小于512个;
若不能满足则使用hashtable。
集合对象
集合对象的编码可以是intset或者hashtable
intset编码的集合对象使用整数集合作为底层实现。
hashtable编码使用字典作为底层实现,哈希对象中的每个键值对都使用一个字典键值对来保存。
编码转换:
当列表对象可以同时满足以下两个条件时,列表对象使用intset编码:
列表对象保存的所有元素都是整数。
列表对象保存的元素数量小于512个;
若不能满足则使用hashtable。
有序集合对象
有序集合对象的编码可以是ziplist或者skiplist
ziplist编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员(member),第二个元素则保存元素的分值(score)。
skiplist采用跳跃列表作为底层实现。
编码转换:
当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码:
列表对象保存的所有字符串元素的长度都小于64字节。
列表对象保存的元素数量小于128个;
若不能满足则使用skiplist。
内存回
收采用引用计数法进行回收没有用到的对象。
对象共享
若为1-9999的字符串,则会共享一个内存地址。
对象空转时间
redisObject含有一个LRU属性,该属性记录了对象最后一次被命令程序访问的时间,由此可计算对象空转时间。
总结
redis数据库中的每个键值对的键和值都是一个对象。
redis共有字符串、列表、哈希、集合、有序集合五种类型的对象,每种类型的对象至少都有两种以上的编码方式,不同的编码可以在不同的使用场景上优化对象的使用效率。
服务器在执行某些命令之前,会先检查给定键的类型能否执行指定的命令,而检查一个键的类型就是检查键的值对象的类型。
redis的对象系统带有引用计数实现的内存回收机制。
redis会共享值为0到9999的字符串对象。
对象会记录自己的最后一次被访问时间,这个时间可以用于计算对象的空转时间。