Redis学习笔记(六) 对象

作者: 子时已过 | 来源:发表于2020-05-15 00:17 被阅读0次

    前面我们看了Redis用到的主要数据结构,如简单动态字符串(SDS)、双向链表、字典、压缩列表、整数集合等。

    但是Redis并没有直接使用这些数据结构来实现键值对,而是基于这些数据结构创建了一个对象系统,这个系统包括字符串对象、列表对象、哈希对象、集合对象、有序集合对象,除此之外,redis的对象系统还实现了基于计数技术的内存回收机制,另外redis还通过引用计数技术实现了对象共享机制(适当条件下,多个数据库键共享同一个对象来节约内存)。

    最后,redis的对象带有访问时间记录信息,该信息可以用于计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长较大的键会优先被服务器删除。

    1、Redis中的每个结构都是由redisObject结构标识,包含ptr(指向底层实现的数据结构)、encoding(决定用那种底层数据结构)、type等属性。

    2、当我们创建一个键值对时,我们至少会创建两个对象:键对象(字符串对象),值对象(物种类型)。

    3、字符串对象的编码可以是整数、raw或者enbstr、sds

        1)     enbstr(短字符串长度小于32)调用一次分配内存函数,分配一个连续的内存包含redisObject结构与sdshdr结构,不包含修改命令,执行任何修改命令会转为raw对象。

        2)    sds(字符串长度超过32)。

        3)    raw 会调用两次内存分配分别创建redisObject结构与sdshdr结构。

    4、列表对象,列表对象的编码可以是ziplist或者linkedlist

        1)    ziplist使用压缩列表作为底层实现。列表对象保存的所有字符串元素长度都小于64字节,元素数量小于512个时使用压缩列表做为底层实现。

        2)    linkedlist编码列表对象使用双向链表作为底层实现,每个双向链表节点都保存一个字符串对象。

    5、哈希对象

        1)    哈希对象的编码可以是ziplist或者hashtable

        2)    ziplist编码的哈希对象使用压缩表作为底层实现,当由新的键值对加入到hash对象时,程序会先将保存了键的压缩列表节点推入到压缩列表的表尾,然后将保存了值的压缩列表节点推入到压缩列表的表尾。

        3)    使用hashtable作为编码的哈希对象使用字典作为底层实现,键使用字符串对象,值使用字符串对象。

    6、集合对象

        1)    集合对象的编码可以是 intset或者是hashtable

        2)    intset编码的集合对象使用整数集合作为底层实现。

        3)    hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象包含一个集合元素,而字段的值则全部设置为null。

        4)    对象转换 。intset转hashtable条件:元素中不全是整数或者元素数量超过512.

    7、有序集合对象

        1)    有序集合的编码可以是ziplist 或者skiplist

        2)    ziplist编码的压缩列表对象使用压缩列表作为底层实现,每个集合元素使用两个挨在一起的压缩列表节点来保存,第一个节点保存元素的成员(member)第二个元素则保存元素的分值(score)。

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

    typedefstruct zset{

        zskiplist *zsl;

        dict *dict;//保存从成员到分值的映射,键保存元素成员 值保存了分数。

    }

        4)    解释下为什么同时使用字典与跳跃表来实现有序集合:虽然用两种结构的任意一种都能实现有序集合,但是当我们只是用字典来实现有序集合时,由于字典是一个无序的保存元素,当我们实行范围操作时,需要先对所有的元素进行排序,这里所使用的时间复杂度至少为O(NlogN),并且有额外的内存消费;另外如果只使用跳跃表来实现有序集合时,虽然范围操作的优势被保留,但是没有了字典根据成员查找分值时这一操作的复杂度将从O(1)提升到O(logN)。

        5)   编码转换,当元素的数量小于128,且每个元素的长度都小于64字节时,使用ziplist。

    8、内存回收

        1)    每个对象的引用技术信息由redisObject结构的refcount属性记录。

        2)    创建对象时,计数值会被默认初始化为1,被程序使用时,计数器加一,不再被使用时,计数器减一,当计数器为0时,对象占用的内存会被释放。

    9、对象空转时长

        1)    对象空转时长使用redisObjet结构中的lru属性记录,该属性记录对象最后一次被访问的时间。


    每天学一点,总会有收获。

    说明:尊重作者知识产权,文中内容参考《Redis设计与实现》,仅在此做学习与大家分享。

    相关文章

      网友评论

        本文标题:Redis学习笔记(六) 对象

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