关于redis:redis学习之六对象

30次阅读

共计 1881 个字符,预计需要花费 5 分钟才能阅读完成。

这段时间打算梳理下 redis 相干的知识点,先从 redis 底层的数据结构与 redisObject 对象开始吧。
在开展之前咱们须要先对 redis 的设计准则有一个大略的意识:

  • 存储效率(memory efficiency),在谋求存储效率这一准则的前提下,redis 才会有下面这些数据结构,并且会在某些场景下会交替应用这些数据结构,能够设想的到 redis 会在数据压缩、防止内存碎片方面下功夫。
  • 疾速响应(fast response),一般来说,单台 redis 可达到 4W 左右的 QPS。因为数据是存在内存所以不会呈现磁盘 IO(这也是 redis 不用应用多线程的一个起因),而 redis 的性能瓶颈次要是 内存大小 网络带宽。正是有了底层这些非凡的数据结构撑持,才会有极快的贵响应。

咱们都晓得 redis 里咱们常常应用的数据类型有:

  • string
  • list
  • hash
  • set
  • sorted set

这五种(其它数据类型能够参看:redis 文档),那底层的数据结构是如何撑持这五种数据类型的呢?从源码里能够看出,底层别离是:

  • dict
  • sds
  • ziplist
  • quicklist
  • skiplist

这些构造数据,不过,redis 并没有间接应用这些数据结构来实现键值对,而是基于这些数据结构创立了一个对象零碎,这个零碎蕴含字符串对象、列表对象、哈希对象、汇合对象、和有序汇合对象,每种对象都会应用到至多一种下面提到的数据结构,具体是这样的:

  1. list: 在同时满足上面两种状况下会应用 ziplist: 一是所有字符串长度小于 64 字节;二是元素数量小于 512, 不满足任一条件就会应用 linkedlist(双端链表)。
  2. hash: 在同时满足上面两种状况下会应用 ziplist: 一是所有键值对的键和值的字符串长度都小于 64 字节;二是键值对数量小于 512 个;不满足任意一个都应用 hashtable 编码。
  3. set: 在同时满足上面两种状况下会应用 intset: 一是所有元素都是整数值;二是元素个数小于等于 512 个;不满足任意一条都将应用 hashtable 编码。
  4. zset: 在同时满足上面两种状况下会应用 ziplist: 一是所有元素长度小于 64 字节;二是元素个数小于 128 个;不满足任意一条件将应用 skiplist 编码。

这样做的目标有:

  1. 能够在执行命令之前,依据对象的类型来判断一个对象是否能够执行给定命令。
  2. 能够针对不同的应用场景切换应用适合的数据结构。
  3. redisObject 对象实现了基于援用计数的内存回收机制方便管理内存,同时在援用计数的根底上实现的对象共享机制也利于节约内存。

每次咱们应用 redis 创立一个新的键值对时,至多会创立两个对象:一个是键对象一个是值对象。redisObject 有三个属性别离为 type 属性、encoding 属性、ptr 属性:

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

type 属性记录了对象的类型,其对应的值如下:

类型常量 对象的名称
REDIS_STRING 字符串对象
REDIS_LIST 列表对象
REDIS_HASH 哈希对象
REDIS_SET 汇合对象
REDIS_ZSET 有序汇合对象

咱们能够应用 TYPE 命令来查看值对象的类型。对于 redis 保留的键值来说,键总是一个字符串对象,而值则是下面提到的五种类型对象。

对象的 ptr 属性指针指向对象的底层实现数据结构,而这些数据结构由对象的 encoding 属性决定,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 跳跃表

值对象的编码咱们能够应用 OBJECT 命令进行查看。

总结:通过 encoding 属性来设定对象所应用的编码,而不是为特定类型的对象关联一种固定的编码,极大的晋升了灵活性与效率,redis 能够依据不同的应用场景来抉择特定对象不同的的编码,从而晋升对应场景下的应用效率。

参考的文章有:
黄健宏的《Redis 设计与实现》一书
张铁蕾对于 redis 的文章

正文完
 0