Redis对象类型

Redis对象类型

目录

对象

Redis中的键和值都是由对象来表示,键的对象类型总是字符串,而值则可以是字符串对象、列表对象、哈希对象、集合对象或者有序集合对象的其中一种。

对象结构体定义:

  • type 数据类型

    type的取值如下:

    类型常量对象的名称
    REDIS_STRING字符串对象
    REDIS_LIST列表对象
    REDIS_HASH哈希对象
    REDIS_SET集合对象
    REDIS_ZSET有序集合对象
  • encoding 数据编码

    encoding决定了对象使用的底层数据结构,有如下取值:

    REDIS_ENCODING_INTlong 类型的整数
    REDIS_ENCODING_EMBSTRembstr 编码的简单动态字符串
    REDIS_ENCODING_RAW简单动态字符串
    REDIS_ENCODING_HT字典
    REDIS_ENCODING_LINKEDLIST双端链表
    REDIS_ENCODING_ZIPLIST压缩列表
    REDIS_ENCODING_INTSET整数集合
    REDIS_ENCODING_SKIPLIST跳跃表和字典

字符串对象

编码

字符串对象的编码可以是 intraw 或者 embstr

  • int

  • raw:使用数据结构SDS

  • embstr:使用数据结构SDS

    embstr是用来保存短字符串,使用embstr有以下好处:

    1. embstr 编码将创建字符串对象所需的内存分配次数从 raw 编码的两次降低为一次。
    2. 释放 embstr 编码的字符串对象只需要调用一次内存释放函数, 而释放 raw 编码的字符串对象需要调用两次内存释放函数。
    3. 因为 embstr 编码的字符串对象的所有数据都保存在一块连续的内存里面, 所以这种编码的字符串对象比起 raw 编码的字符串对象能够更好地利用缓存带来的优势。

字符串对象保存各类型值的编码方式

编码
可以用 long 类型保存的整数。int
可以用 long double 类型保存的浮点数。embstr 或者 raw
字符串值, 或者因为长度太大而没办法用 long 类型表示的整数, 又或者因为长度太大而没办法用 long double 类型表示的浮点数。embstr 或者 raw

编码转换

  • int编码的字符串通过某种操作之后,比如末尾添加字符的操作,会被转换成raw或者embstr编码。
  • embstr也可以被转成raw编码

列表对象

编码

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

  • ziplist:压缩列表数据结构

    image-20190105175238909

  • linkedlist:双端链表数据结构

    image-20190105175253739

编码转换

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

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

不能满足这两个条件的列表对象需要使用 linkedlist 编码。

以上两个条件的上限值是可以修改的, 具体请看配置文件中关于 list-max-ziplist-value 选项和 list-max-ziplist-entries 选项的说明。

哈希对象

编码

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

  • ziplist 压缩列表数据结构

    image-20190105175811981

  • hashtable: 压缩表

    image-20190105175846484

编码转换

当哈希对象可以同时满足以下两个条件时, 哈希对象使用 ziplist 编码:

  1. 哈希对象保存的所有键值对的键和值的字符串长度都小于 64 字节;
  2. 哈希对象保存的键值对数量小于 512 个;

不能满足这两个条件的哈希对象需要使用 hashtable 编码。

这两个条件的上限值是可以修改的, 具体请看配置文件中关于 hash-max-ziplist-value 选项和 hash-max-ziplist-entries 选项的说明。

集合对象

编码

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

  • inset:整数集合数据结构

    image-20190105180235486

  • hashtable:哈希表数据结构

    image-20190105180306266

编码转换

当集合对象可以同时满足以下两个条件时, 对象使用 intset 编码:

  1. 集合对象保存的所有元素都是整数值;
  2. 集合对象保存的元素数量不超过 512 个;

不能满足这两个条件的集合对象需要使用 hashtable 编码。

第二个条件的上限值是可以修改的, 具体请看配置文件中关于 set-max-intset-entries 选项的说明。

有序集合对象

编码

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

  • ziplist 压缩列表

    image-20190105232527360

    image-20190105232539991

  • skiplist 基于跳表+字典

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

    通过这个字典, 程序可以用 O(1) 复杂度查找给定成员的分值。

    image-20190105232708490

    编码转换

    当有序集合对象可以同时满足以下两个条件时, 对象使用 ziplist 编码:

    1. 有序集合保存的元素数量小于 128 个;
    2. 有序集合保存的所有元素成员的长度都小于 64 字节;

    不能满足以上两个条件的有序集合对象将使用 skiplist 编码。

    以上两个条件的上限值是可以修改的, 具体请看配置文件中关于 zset-max-ziplist-entries 选项和 zset-max-ziplist-value 选项的说明。

 

内存回收

采用引用计数

对象共享

Redis 只对包含整数值的字符串对象进行共享。

不共享包含字符串的对象的原因?验证共享对象和目标对象是否相同所需的复杂度高,需要O(n)的时间。所以从CPU资源的角度来看,不对字符串进行共享。

参考

  1. 书籍《Redis设计与实现》