美文网首页
Redis对象(一) - 类型和编码

Redis对象(一) - 类型和编码

作者: 牛牛_735d | 来源:发表于2020-04-28 21:08 被阅读0次

    对象

    前边学习了Redis底层实现的各种数据结构, 包括SDS, list, skiplist, dict, intset, ziplist等, 但redis并未直接使用这些数据结构来构建数据库、而是基于这些数据结构构建了一个对象系统, 这个系统包括 字符串对象, 列表对象, hash对象, 集合对象, 有序集合对象这五种类型的对象.

    通过这5种不同的对象、Redis可以在执行命令前, 根据对象的类型来判断一个对象是否可以执行给定的命令, 使用对象的另一个好处是, 可以针对不同的使用场景、为对象设置不同的数据结构的实现、优化对象在不同使用场景下的使用效率.

    此外、Redis的对象系统还实现了基于引用计数技术的内存回收机制、当程序不再使用某个对象时、对象占用的内存会被自动释放, 且: Redis 还通过引用计数技术实现了对象共享机制, 可以在适当调节下、让多个数据库键共享同一个对象来节约内存

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

    对象的类型和编码

    Redis使用对象表示数据库中的键和值, 当在redis数据库中创建一个键值对时、至少会创建两个对象: 键对象 和 值对象. eg. Set 命令在数据库中创建一个键值对

    redis> set msg "hello world"
    OK
    

    就包含了一个键对象msg的字符串对象 和 一个值对象 hello world

    Redis中每个对象由一个redisObject结构表示, 和保存数据有关的3个属性分表是 type属性encoding属性ptr属性

    typedef struct redisObject {
      unsigned type:4; // 类型
      unsigned encoding:4; // 编码
      void *ptr; // 指向底层实现数据结构的指针
      //...
    }
    
    类型

    对象的type属性记录了对象的类型, 属性值可以是下边任何一个

    类型常量 对象名称 type命令输出
    REDIS_STRING 字符串对象 String
    REDIS_LIST 列表对象 List
    REDIS_HASH hash对象 Hash
    REDIS_SET 集合对象 Set
    REDIS_ZSET 有序集合对象 Zset

    对于Redis保存的键值对来说、键总是一个字符串对象, 而值则可以是上边任意一种对象, 所以:

    1. 当我们称呼一个键为字符串键时, 指的是对应的值是字符串对象
    2. 当我们称呼一个键为列表键时, 指的是对应的值是列表对象

    type命令的实现方式与此类似, 执行type命令返回的是值对象的类型, 而不是键对象的类型

    编码和底层实现

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

    encoding属性记录了对象使用的编码, 即 对象使用了什么数据结构作为对象的底层实现, 可以是下表的任意一个

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

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

    类型 编码 对象
    redis_string redis_encoding_int<br />redis_encoding_embstr
    redis_encoding_raw
    使用整数值实现的字符串对象<br />使用embstr编码的简单动态字符串
    用简单动态字符串实现的字符串对象
    redis_list redis_encoding_ziplist<br />redis_encoding_linkedlist 使用压缩列表实现的列表对象<br />使用双端链表实现的列表对象
    redis_hash redis_encoding_ziplist<br />redis_encoind_ht 使用压缩列表实现的hash对象<br />使用字典实现的hash对象
    redis_set redis_encoding_intset<br />redis_encoding_ht 使用整数集合实现的集合对象<br />使用字典实现的集合
    redis_zset Redis_encoding_ziplist
    redis_encoding_skiplist
    使用压缩列表实现的有序集合对象
    使用跳表实现的有序集合对象

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

    redis> set msg "hello world"
    OK
    
    redis> object encoding msg
    "embstr"
    
    redis> set story "long long long ..."
    OK
    
    redis> object encoding story
    "raw"
    

    通过encoding属性来设定对象使用的编码、而不是为特定类型的对象关联一种固定的编码、极大的提高了redis的灵活性和效率, 允许redis在特定场景下未一个对象设置不同的编码, 优化使用效率.

    eg. 在列表包含对象较少时, redis使用压缩列表作为底层实现, 因为:

    1. 压缩列表比双端链表节省内存, 且元素数量少时、在内存中连续存储的压缩列表比双端链表可以更快的载入缓存
    2. 随元素增多、使用压缩列表保存元素的优势消失时、对象会将底层实现从压缩列表转向功能更强、也适合保存大量元素的双端链表上

    其它类型的对象也会使用不同类型的编码进行类似的优化

    相关文章

      网友评论

          本文标题:Redis对象(一) - 类型和编码

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