Redis学习与总结二:Redis的五大数据对象

      概述: Redis使用对象来表示数据库中的键和值,每次在Redis的数据库中创建一个键值对时,至少会创建两个对象,一个键对象,一个值对象。其中键总是一个字符串对象,而值则可以是字符串对象、列表对象、哈希对象·、集合对象、有序集合对象中的一种。

     对象的ptr指针指向对象的底层实现数据结构,而这些数据结构由对象的encoding属性决定,每种类型的对象都至少使用了两种不同类型的编码。

                   Redis学习与总结二:Redis的五大数据对象_第1张图片

1、字符串对象 

       字符串对象的编码可以是int、embstr及raw。 字符串对象可以是int、raw或者embstr。如果一个字符串是整数,并且可用long型表示,那么该字符串对象编码就是int。如果字符串长度大于32字节,那么将使用一个简单动态字符串(sds)保存,并将对象编码设置为raw。如果字符串长度小于等于32字节,则字符串以编码方式embstr来保存该字符串值。(embstr编码通过调用一次内存分配函数来分配一块连续的空间,但raw编码会调用两次内存分配函数来分配一块连续的空间)

2、列表对象 

      列表对象的编码可以是ziplist 或者linkedlist。ziplist使用功能压缩列表作为底层实现,每个压缩列表节点保存一个列表元素。linkedlist编码的列表对象使用双端链表作为底层实现,每个双端链表节点都保存了一个字符串对象,而每个字符串对象都保存了一个列表元素。linkedlist编码的列表对象在底层双端链表结构中包含了多个字符串对象,这个嵌套字符串对象行为在哈希表、集合中都会出现,字符串对象是Redis五种类型中唯一一种会被其他四种类型对象嵌套的对象。列哈希象保存的所有字符串长度都小于64字节并且列表保存的元素数量小于512个时使用ziplist编码实现,否则使用hashtable编码实现。注意这个512的值是可以修改的,具体参见配置项hash-max-ziplist-value和hash-max-ziplist-entries选项。 

3、哈希对象 

        哈希对象的编码可以是ziplist或者hashtable。ziplist编码的哈希对象使用压缩列表作为底层实现,当有新的键值对要加入哈希对象时,会先将保存了键的压缩列表节点推入到压缩列表表尾,再将保存了值的压缩列表节点推入到列表表尾。这样的话,一对键值对总是相邻的,并且键节点在前值节点在后。如果hashtable编码的哈希对象使用字典作为底层实现,则哈希对象中的每个键值对都是字典键值对来保存(字典的每个键都是一个字符串对象,对象中保存了键值对的键;字典的每个值都是一个字符串对象,对象中保存了键值对的值)。哈希对象保存的所有字符串长度都小于64字节并且列表保存的元素数量小于512个时使用ziplist编码实现,否则使用hashtable编码实现。注意这个512的值是可以修改的,具体参见配置项hash-max-ziplist-value和hash-max-ziplist-entries选项。 

4、集合对象 

       集合对象的编码可以是intset或者hashtable。intset编码的集合对象使用整数集合作为底层实现,所有元素都保存在整数集合中。另一方面,使用hashtable的集合对象使用字典作为底层实现,字典中每个键都是一个字符串对象,即一个集合元素,而字典的值都是NULL的。集合对象所有的元素都是整数值并且集合对象数量不超过512个时使用intset实现,否则使用hashtable实现。注意,这里的512值是可以修改的,具体参见配置项set-max-intset-entries选项。 

5、有序集合对象 

        有序集合对象的编码可以是ziplist或者skiplist。ziplist编码的压缩列表对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨着的压缩列表节点保存,第一个保存集合元素,第二个保存集合元素对应的分值。压缩列表内集合元素按照分值大小进行排序,分值较小的在前,分值大的在后。skiplist编码的有序集合对象使用zset结构作为底层实现,一个zset结构同时包含一个字典和一个跳跃表。zset中的dict字典为有序集合创建了一个从成员到分值的映射,字典中的每个键值对都保存了一个集合元素,字典的键保存集合元素的成员,字典的值保存集合成员的分值。通过该字典,可以O(1)复杂度查找到特定成员的分值,zscore命令就是根据这一特性来实现的。有序集合中保存的元素数量小于128个且有序集合中保存的·所有元素成员的长度都小于64字节时使用ziplist编码,否则使用skiplkist编码

6、总结

1、redis数据库中的每个键值对的“键”与“值”都是一个redisObject对象; 
2、redis共有字符串、列表、哈希、集合及有序集合5种类型的对象,每种类型的对象都有至少两种或者以上的编码方式,不同的编码可以在不同的场景上使用,以优化对象的使用效率,整体上的原则是当数据量比较少时,采用一种编码方式,当数据量比较大时,采用另一种编码方式,后者可以更消耗内存(这点可以通过配置文件实现,但不是全部的条件都可以配置,此外,具体的默认配置在不同版本也不一样)。从这种上也可以看出来redis作者声明的关于redis是追求性能这一点的; 
3、服务器在执行某些命令之前,会先检查给定键的类型能否执行指定的命令,而检查一个键的类型就是检查键的值的类型; 
4、redis的对象系统带有引用计数实现的内存回收机制,当一个对象不再被使用时,该对象所占用的内存就会被自动释放; 
5、redis会共享值为0到9999的字符串对象,本质上是共享值为整数类型的字符串对象; 
6、对象会记录自己的最后一次被访问的时间,这个时间可以用于计算对象的空转时间,当需要清理内存空间时可以提供依据。
 

你可能感兴趣的:(Redis)