• 第八章 对象


    Redis中的对象:

    • 字符串对象
    • 列表对象——压缩列表或双端链表
    • 哈希对象——压缩列表或字典
    • 集合对象——整数集合或字典
    • 有序集合对象——压缩列表或跳表+字典

    每个对象针对不同的使用场景选择底层实现,并使用引用计数器决定对象的回收,某些条件下可以通过引用计数器实现共享。

    8.1 对象的类型和编码

      Redis中的键和值都是对象,键固定是字符串对象,称某某键指的是值对象。譬如列表键,即值是列表对象。redisObject的结构和对象类型编码内存回收共享对象都有关系,一个对象内存占用 4bit+4bit+24bit+4byte+8byte=16byte

    typedef struct redisObject{
        //对象类型
        unsigned type:4bit;
        //实现对象的编码方式
        unsigned encoding:4bit;
        //指向底层实现数据结构的指针,在64位系统中,一个指针8字节 
        void *ptr:8byte;
        ....
        //引用计数,int占用4字节
        int refcount:4byte; 
        //最后一次被命令程序访问的时间,在2.6版本是22bit,在4.0版本是24bit
        unsigned lru:22bit; 
    
    }

    8.2 字符串对象

      编码方式:

    • int编码:字符串对象保存的值是整数值(long)
    • raw编码:字符串对象保存的值是字符串,并且长度大于39字节,使用SDS实现
    • embstr编码:针对段字符串的优化,减少分配和释放需要的内存分配次数  

      raw编码和embstr编码也可以保存浮点数

      字符串对象大小不能超过512M

      8.2.1 编码的转换

      int编码的值被修改成字符串、embstr编码的值一旦被修改(例如APPEND操作),都会被转换成raw编码方式。

    8.3 列表对象

      redis> RPUSH numbers 1 "three" 5

      编码方式:

    • ziplist编码:底层使用压缩列表实现

      

    • linkedist编码:使用双端列表实现

      

      当列表对象保存的所有字符串元素的长度小于64字节,且对象保存的元素数量小于512个时,使用ziplist编码,否则使用linkedlist编码

    8.4 哈希对象

      编码方式:

    • ziplist编码:使用压缩列表实现。当有新键值对插入时,先将键的压缩列表节点推入列表的尾部,再将值的压缩列表节点推入列表的尾部。
    • hashtable编码:使用字典实现。

        当哈希对象保存的所有键值对的字符串都小于64字节,并且键值对的数量小于512个,使用ziplist编码,否则使用hashtable编码

    8.5 集合对象

      redis>SADD numbers 1 3 5

      编码方式:

    • intset编码:使用整数集合实现。
    • hashtable编码:使用字典实现。字典的每个键都是字符串对象,保存了一个集合的值,字典的值全部设置为NULL。

      当保存的集合的元素都是整数,并且总数不超过512个时,使用intset编码,否则使用hashtable编码

    8.6 有序集合对象

      编码方式:

    • ziplist编码:每个元素使用两个压缩列表节点表示,第一个存放元素的值,第二个存放元素的分值。元素按照分值大小从小到大排序,分值越大越靠近表尾。
    • skiplist编码:使用跳表+字典实现。

      在跳表的实现中,每个节点的object保存了元素的值,score保存了分值。使用ZRANK和ZRANGE等范围操作可以有效的使用跳表排序的特性。

      在字典的实现中,字典键存放元素的值,字典值存放元素的分数。查找每个元素的分值的复杂度是常量级。

      同时使用跳表和字典实现,会用指针来共享元素的成员和分值,所以不会造成额外内存的浪费。还能结合二者的优势。

      当保存的集合的元素数量小于128个,而且所有元素的长度都小于64字节时,使用ziplist编码,否则使用skiplist实现。

    8.7 类型检查和命令多态

    • 类型检查:不同的命令针对不同的对象,Redis在执行特定命令时,会通过对象中的type属性检查输入键的类型是否正确。
    • 多态命令:同一个命令的目标对象,底层的实现不同,调用的API也不同,Redis通过encoding属性得知具体的底层实现,调用不同的API。

    8.8 内存回收

      对象的refcount属性记录了引用关系

    • 创建新对象时,引用计数器初始化成1
    • 当对象被一个新的程序使用时,计数器值+1
    • 当对象不再被某个程序使用时,计数器值-1
    • 当对象的引用计数器值变成0,对象占用的内存被释放

    8.9 对象共享

      当一个对象被多个程序使用时,譬如键A的值对象和键B的值对象相同时,只会创建一个对象,A和B的值对象都指向该对象,同时该对象的引用计数器记为2。受到CPU时间的限制,Redis只对包含整数值的字符串对象进行共享。目前Redis会共享0~9999的字符串对象。

    8.10 对象的空转时常

      对象的lru属性,记录了对象最后一次被命令程序访问的时间。OBJECT IDLETIME命令可以打印出给定键的lru属性,并且不会更改lru属性。

    人生就像蒲公英,看似自由,其实身不由己。
  • 相关阅读:
    python高级编程
    django笔记
    sublime ide
    python3 django mysql
    python win
    linux时区设置
    在实际应用中如何实现切圆角的功能
    display和visiblity在应用中使用哪个好
    看懂UML类图和时序图
    解决Xcode7.2真机调试出现:The account “” has no team with ID “”
  • 原文地址:https://www.cnblogs.com/walker993/p/14438753.html
Copyright © 2020-2023  润新知