redis中的对象

作者: BlackChen | 来源:发表于2018-01-11 14:40 被阅读65次

    redis的对象包含5种对象:

    • 字符串对象
    • 列表对象
    • 哈希对象
    • 集合对象
    • 有序集合对象

    redis对象的好处

    • 针对不同的使用场景,为对象设置多种不同的数据结构实现,优化对象不同场景下的使用效率.
    • 对象实现了基于引用计数计数的内存回收机制
      1. 当redis不再使用某个对象的时候,这个对象所占用的内存就会被释放.
      2. redis还通过引用计数实现对象的共享机制,可以节约内存.
    • 对象带有访问时间记录信息,可以通过该信息计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长较大的键会被服务器删除.

    对象结构

    typedef struct redisObject {
    
        // 类型
        unsigned type:4;
    
        // 编码
        unsigned encoding:4;
    
        // 对象最后一次被访问的时间
        unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
    
        // 引用计数
        int refcount;
    
        // 指向实际值的指针
        void *ptr;
    
    } robj;
    
    • 类型 type
      type 记录了对象的类型,可以是一下值重点任意一个

      1. REDIS_STRING 字符串对象
      2. REDIS_LIST 列表对象
      3. REDIS_HASH 哈希对象
      4. REDIS_SET 集合对象
      5. REDIS_ZSET 有序集合对象
    • 底层编码实现 encoding
      对象的ptr指针指向对象底层实现的数据结构,这些数据结构由encoding来决定

    编码常量 编码对应底层数据结构
    REDIS_ENCODING_INT long类型整数
    REDIS_ENCODING_EMBSTR embstr编码的简单动态字符串
    REDIS_ENCODING_RAW 简单动态字符串
    REDIS_ENCODING_HT 字典
    REDIS_ENCODING_LINKEDLIST 双端链表
    REDIS_ENCODING_ZIPLIST 压缩列表
    REDIS_ENCODING_INTSET 整数集合
    REDIS_ENCODING_SKIPLIST 跳跃表和字典

    每种类型(type)的对象至少使用两种不同的编码.

    类型(type) 编码(encoding) 对象
    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


      image.png

    raw 和 embstr的区别:

    • raw调用两次内存分配函数来分别创建redisObject结构和sdshdr结构
    • embstr调用一次内存分配函数来分配一块连续的空间,依次包含redisOject和sdshdr

    列表对象

    底层实现

    • ziplist


    • linkedlist


    注意: linekedlist 编码的列表对象再地城的双端链表结构中包含了多个字符串对象,字符串对象是redis五中类型的对象中唯一一种会被其他4中类型对象嵌套的对象

    编码转换

    当列表对象可以同时满足以下两个条件时,列表对象使用ziplist.

    • 列表对象保存的所有字符串元素的长度都小于64字节
    • 列表对象保存的元素数量小于512个.

    这两个值可以在配置文件中进行修改:

    • list-max-ziplist-value
    • list-max-ziplist-entries

    哈希对象

    底层实现

    • zipList
      当有新的键值对要加入哈希对象时,程序会先姜保存了键的压缩列表节点推入到压缩列表表尾,然后再将保存了值的压缩列表节点推入压缩列表结尾



    -hashTable


    编码转换

    • 哈希对象保存所有键值对的键和值字符串长度不小于64字节
    • 哈希对象保存的键值对数量小于512个
      不满足这两个条件,哈希对象使用hashtable编码

    集合对象

    底层实现

    • intset


    • hashtable


    编码转换

    • 集合对象保存所有元素都是整数值
    • 集合对象保存的元素数量不超过512个
      不满足两个条件的集合对象要使用hashTable

    有序集合对象

    底层实现

    • ziplist
      有序集合对象使用ziplist实现时,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,而第二个元素保存元素的分值.



    • skiplist
      skiplist编码的有序集合对象使用zset结构作为底层实现.

    /*
     * 有序集合
     */
    typedef struct zset {
    
        // 字典,键为成员,值为分值
        // 用于支持 O(1) 复杂度的按成员取分值操作
        dict *dict;
    
        // 跳跃表,按分值排序成员
        // 用于支持平均复杂度为 O(log N) 的按分值定位成员操作
        // 以及范围操作
        zskiplist *zsl;
    
    } zset;
    

    zset结构中,跳跃表按照分值从小到大保存了所有集合的元素
    zset结构中,dict字典为有序结合创建了一个从成员到分值的映射,字典的键保存了元素的成员,字典的值,保存了元素的分值
    两种数据结构,通过指针来共享相同的元素成员和分值,不会浪费额外的内存.

    注意: 图中为了方便展示,显示了各个元素的成员和分值,实际中,字典和跳跃表会共享元素的成员和分值

    编码和转换

    • 有序集合保存的元素数量小于128个
    • 有序集合保存的所有元素成员长度小于64字节

    对象的内存回收

    Redis使用引用计数来实现内存回收机制

    • 创建新对象时,引用计数的值会初始化为1
    • 当对象被新程序使用时,引用计数j+1
    • 当不被y9ige程序使用时,引用 -1
    • 当引用计数为0 时,会被释放

    对象共享

    Redis会在初始化服务器时,创建一万个字符串对象,这些对象包含了从0到9999的所有整数值,服务器使用这些对象时,服务器会共享这些对象,而不是创建新的

    对象空转时长

    对象的lru属性,记录了对象最后一次被命令访问的时间
    服务器打开了Maxmemory选项,并且服务器用于回事欧内存的算法为volatile-lru或者allkeys-lru,那么当服务器占用的内存超过了maxmemory选项所设置的上限值,空转时长较高的那部分键会被优先释放

    总结

    • redis 有五种对象
      • 字符串对象
        实现方式: int, embstr, raw
      • 列表对象
        实现方式: ziplist,linkedlist
      • 哈希对象
        实现方式: ziplist,hashtable
      • 集合对象
        实现方式: intzet,hashtable
      • 有序集合对象
        实现方式: ziplist,zset-{hashtable,skiplist}

    相关文章

      网友评论

        本文标题:redis中的对象

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