美文网首页
第八章 对象

第八章 对象

作者: 今天不想掉头发 | 来源:发表于2019-07-26 10:59 被阅读0次

redis基于SDS、双端链表、字典等数据结构创建了一个对象系统,包括字符串对象、列表对象、哈希对象、集合对象和有序集合对象。

redis使用对象来表示数据库中的键和值,每当在redis中新创建一个键值对时,至少会创建2个对象。reds中的每个对象都是用一个redisObject结构来表示:


image.png

数据库的对象类型一共有如下5种:


image.png

键总是一个字符串对象,而值可以是上述的5种任意一种对象。

redis中的每种对象可以有多少不同的编码和底层实现,可以实现一定条件下灵活的转化,从而优化对象在某一场景下的效率:


image.png

字符串对象

字符串对象的编码可以是int、raw或者embstr。
1.字符串对象保存整数值,且可以用long类型表示,则使用整数值来表示,并且字符串编码为int


image.png

2.字符串对象保存字符串值,且长度大于39字节,则使用一个SDS数据结构来表示,并且字符串编码为raw


image.png

3.字符串对象保存字符串值,且长度小于等于39字节,那么用embstr的字符串编码(同样使用SDS的数据结构,但是redisobject和SDS的内存是连续的,可以很好地利用缓存的优势)


image.png

字符串编码是可以转换的,比如对int编码的字符串可以变成raw等等。

列表对象

列表对象的编码可以是ziplist(压缩列表)或者linkedlist(双端列表)。
对于操作


image.png

如果值对象使用ziplist编码,则如下所示:


image.png

如果值对象使用linkedlist编码,则如下所示:


image.png

每个双端链表节点都保存了一个字符串对象,而每个字符串对象都保存了一个列表元素(双端链表底层使用字符串对象进行嵌套)。
其中,StringObject实际上是下图的一个简化:


image.png

列表编码同样是可以转换的,当列表对象保存的所有字符串长度小于64字节且列表对象保存的元素数量小于512个时,列表对象使用ziplist编码;否则,使用linkedlist进行编码。

哈希对象

哈希对象的编码可以是ziplist或者hashtable。
对于操作:


image.png

如果使用ziplist进行编码,则如下所示:


image.png
即先将键添加到压缩列表表尾,然后将值添加到压缩列表表尾

如果使用hashtable进行编码,则如下所示:


image.png

其中,字典的每个键都是一个字符串对象,每个值也是一个字符串对象。

哈希对象编码同样是可以转换的,当哈希对象保存的所有键值对的键和值的字符串长度小于64字节且哈希对象保存的键值对数量小于512个时,哈希对象使用ziplist编码;否则,使用hashtable进行编码。

集合对象

集合对象的编码可以是intset(整数集合)或者hashtable。
对于操作:


image.png
image.png image.png
image.png

需要注意的是,使用hashtable的集合对象的值都为NULL。

集合对象编码同样可以转化,当集合对象保存的所有元素都是整数且元素数量不超过512个时,使用intset编码;否则,使用hashtable进行编码。

有序集合

有序集合的编码可以是ziplist或者skiplist。
1.ziplist中每个集合元素使用2个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。压缩列表内的集合元素分值从小到大排序。


image.png

2.skiplist编码的有序集合使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表:

image.png
image.png
之所以同时使用字典和跳跃表是为了查找的时候O(1)(字典的特性),以及能够利用跳跃表有序的特性来实现范围查找。

有序集合对象编码同样可以转化,当有序集合保存的元素数量小于128个且有序集合保存的所有元素成员的长度都小于64字节时,使用ziplist编码;否则,使用skiplist进行编码。

除了上述一些特点之外,还有一些需要说明:
1.类型检查与命令多态:redis会根据某个对象的编码调用底层不同数据结构的方法,并且调用之前会检查调用对象的type是否正确。
2.内存回收:引用计数实现内存回收。
3.对象共享:对于相同的值,只会在内存中保留一份,通过键指针指向现有的值对象,并将共享对象的值对象引用计数+1来实现。redis默认初始化服务器的时候就会创建0-9999共10000个字符串对象用于共享。注意:redis值共享包含整数值的字符串对象
4.对象的空转时长:redisObject通过lru属性记录对象最后一次被命令程序访问的时间

相关文章

网友评论

      本文标题:第八章 对象

      本文链接:https://www.haomeiwen.com/subject/gmglrctx.html