• 「Redis数据结构」RedisObject


    Redis数据结构」RedisObject

    一、概述

    redisObject对象非常重要,Redis对象的类型内部编码内存回收共享对象等功能,都需要redisObject支持。

    redis 不是一个普通的 key-value存储器,其中 key 类型一般为字符串,而 value 类型则为 redis 对象(redis object)redis 对象可以绑定各种类型的数据,如 string、list 和 set等等。


    二、结构

    RedisObject

    • 使用者的角度来看,⼀个Redis节点包含多个database(非cluster模式下默认是16个,cluster模式下只能是1个),而一个database维护了从key space到object space的映射关系。这个映射关系的key是string类型,⽽value可以是多种数据类型,比如:string, list, hash、set、sorted set等。我们可以看到,key的类型固定是string,而value可能的类型是多个。
    • Redis内部实现的⾓度来看,database内的这个映射关系是用⼀个dict来维护的。dict的key固定用⼀种数据结构来表达就够了,这就是动态字符串sds。而value则比较复杂,为了在同⼀个dict内能够存储不同类型的value,这就需要⼀个通⽤的数据结构,这个通用的数据结构就是robj,全名是redisObject。

    image-20221205012924009


    三、编码方式

    对象的 ptr 指针指向对象的底层实现数据结构, 而这些数据结构由对象的 encoding 属性决定。

    encoding 属性记录了对象所使用的编码, 也即是说这个对象使用了什么数据结构作为对象的底层实现

    Redis中会根据存储的数据类型不同,选择不同的编码方式,共包含11种不同类型:

    编号编码方式说明
    0OBJ_ENCODING_RAWraw编码动态字符串
    1OBJ_ENCODING_INTlong类型的整数的字符串
    2OBJ_ENCODING_HThash表(字典dict)
    3OBJ_ENCODING_ZIPMAP已废弃
    4OBJ_ENCODING_LINKEDLIST双端链表
    5OBJ_ENCODING_ZIPLIST压缩列表
    6OBJ_ENCODING_INTSET整数集合
    7OBJ_ENCODING_SKIPLIST跳表
    8OBJ_ENCODING_EMBSTRembstr的动态字符串
    9OBJ_ENCODING_QUICKLIST快速列表
    10OBJ_ENCODING_STREAMStream流

    每种类型的对象都至少使用了两种不同的编码

    类型编码对象
    REDIS_STRINGREDIS_ENCODING_INT使用整数值实现的字符串对象。
    REDIS_STRINGREDIS_ENCODING_EMBSTR使用 embstr 编码的简单动态字符串实现的字符串对象。
    REDIS_STRINGREDIS_ENCODING_RAW使用简单动态字符串实现的字符串对象。
    REDIS_LISTREDIS_ENCODING_ZIPLIST使用压缩列表实现的列表对象。
    REDIS_LISTREDIS_ENCODING_LINKEDLIST使用双端链表实现的列表对象。
    REDIS_HASHREDIS_ENCODING_ZIPLIST使用压缩列表实现的哈希对象。
    REDIS_HASHREDIS_ENCODING_HT使用字典实现的哈希对象。
    REDIS_SETREDIS_ENCODING_INTSET使用整数集合实现的集合对象。
    REDIS_SETREDIS_ENCODING_HT使用字典实现的集合对象。
    REDIS_ZSETREDIS_ENCODING_ZIPLIST使用压缩列表实现的有序集合对象。
    REDIS_ZSETREDIS_ENCODING_SKIPLIST使用跳跃表和字典实现的有序集合对象。

    使用 OBJECT ENCODING 命令可以查看一个数据库键的值对象的编码:

    redis> SET msg "hello wrold"
    OK
    
    redis> OBJECT ENCODING msg
    "embstr"
    
    redis> SET story "long long long long long long ago ..."
    OK
    
    redis> OBJECT ENCODING story
    "raw"
    
    redis> SADD numbers 1 3 5
    (integer) 3
    
    redis> OBJECT ENCODING numbers
    "intset"
    
    redis> SADD numbers "seven"
    (integer) 1
    
    redis> OBJECT ENCODING numbers
    "hashtable"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    OBJECT ENCODING 对不同编码的输出

    对象所使用的底层数据结构编码常量OBJECT ENCODING 命令输出
    整数REDIS_ENCODING_INT"int"
    embstr 编码的简单动态字符串(SDS)REDIS_ENCODING_EMBSTR"embstr"
    简单动态字符串REDIS_ENCODING_RAW"raw"
    字典REDIS_ENCODING_HT"hashtable"
    双端链表REDIS_ENCODING_LINKEDLIST"linkedlist"
    压缩列表REDIS_ENCODING_ZIPLIST"ziplist"
    整数集合REDIS_ENCODING_INTSET"intset"
    跳跃表和字典REDIS_ENCODING_SKIPLIST"skiplist"

    通过 encoding 属性来设定对象所使用的编码, 而不是为特定类型的对象关联一种固定的编码, 极大地提升了 Redis 的灵活性和效率, 因为 Redis 可以根据不同的使用场景来为一个对象设置不同的编码, 从而优化对象在某一场景下的效率。

    举个例子, 在列表对象包含的元素比较少时, Redis 使用压缩列表作为列表对象的底层实现:

    • 因为压缩列表比双端链表更节约内存, 并且在元素数量较少时, 在内存中以连续块方式保存的压缩列表比起双端链表可以更快被载入到缓存中;
    • 随着列表对象包含的元素越来越多, 使用压缩列表来保存元素的优势逐渐消失时, 对象就会将底层实现从压缩列表转向功能更强、也更适合保存大量元素的双端链表上面;

    其他类型的对象也会通过使用多种不同的编码来进行类似的优化。


    四、小结

    • redisObjec是联结两个层面的数据结构的桥梁。
    • 为多种数据类型提供一种统一的表示方式。
    • 允许同一类型的数据采用不同的内部表示,从而在某些情况下尽量节省内存。
    • 支持对象共享和引用计数。当对象被共享的时候,只占用一份内存拷贝,进一步节省内存。

    五、参考

    对象的类型与编码

    redisObject详解

  • 相关阅读:
    在Ubuntu中,使指定搜索动态库文件路径的环境变量LD_LIBRARY_PATH永久生效
    Jetson 系列(二十九) Nebula Graph
    ROS 笔记(06)— 话题消息的定义和使用
    Go语言学习日记【三十二】golang代码错误处理【error,defer,recover】
    防火墙内容安全笔记
    时序预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络时间序列预测
    【C++】STL——string(两万字详解)
    三方对接「心得」与「体会」
    SpringBoot学习笔记-创建个人中心页面(下)
    copy模块的copy()和deepcopy()
  • 原文地址:https://blog.csdn.net/u014571143/article/details/128180182