redis中的对象

作者: BlackChen | 来源:发表于2018-01-11 14:40 被阅读65次

redis的对象包含5种对象:

  • 字符串对象
  • 列表对象
  • 哈希对象
  • 集合对象
  • 有序集合对象

redis对象的好处

  • 针对不同的使用场景,为对象设置多种不同的数据结构实现,优化对象不同场景下的使用效率.
  • 对象实现了基于引用计数计数的内存回收机制
    1. 当redis不再使用某个对象的时候,这个对象所占用的内存就会被释放.
    2. redis还通过引用计数实现对象的共享机制,可以节约内存.
  • 对象带有访问时间记录信息,可以通过该信息计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长较大的键会被服务器删除.

对象结构

typedef struct redisObject {

    // 类型
    unsigned type:4;

    // 编码
    unsigned encoding:4;

    // 对象最后一次被访问的时间
    unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */

    // 引用计数
    int refcount;

    // 指向实际值的指针
    void *ptr;

} robj;
  • 类型 type
    type 记录了对象的类型,可以是一下值重点任意一个

    1. REDIS_STRING 字符串对象
    2. REDIS_LIST 列表对象
    3. REDIS_HASH 哈希对象
    4. REDIS_SET 集合对象
    5. REDIS_ZSET 有序集合对象
  • 底层编码实现 encoding
    对象的ptr指针指向对象底层实现的数据结构,这些数据结构由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 跳跃表和字典

每种类型(type)的对象至少使用两种不同的编码.

类型(type) 编码(encoding) 对象
REDIS_STRING REDIS_ENCODING_INT 使用整数值实现的字符串对象
REDIS_STRING REDIS_ENCODING_EMBSTR 使用EMBSTR编码的简单动态字符串实现的字符串对象
REDIS_STRING REDIS_ENCODING_RAW 使用简单动态字符串实现的字符串对象
REDIS_LIST REDIS_ENCODING_ZIPLIST 使用压缩列表实现的列表对象
REDIS_LIST REDIS_ENCODING_LINKEDLIST 使用双端链表实现的列表对象
REDIS_HASH REDIS_ENCODING_ZIPLIST 使用压缩列表实现哈希对象
REDIS_HASH REDIS_ENCODING_HT 使用字典实现哈希对象
REDIS_SET REDIS_ENCODING_INTSET 使用整数集合实现集合对象
REDIS_SET REDIS_ENCODING_HT 使用字典实现集合对象
REDIS_ZSET REDIS_ENCODING_ZIPLIST 使用压缩列表实现有序集合对象
REDIS_ZSET REDIS_ENCODING_SKIPLIST 使用跳跃表和字典实现有序集合对象

字符串对象

底层实现

  • int


  • raw


  • embstr


    image.png

raw 和 embstr的区别:

  • raw调用两次内存分配函数来分别创建redisObject结构和sdshdr结构
  • embstr调用一次内存分配函数来分配一块连续的空间,依次包含redisOject和sdshdr

列表对象

底层实现

  • ziplist


  • linkedlist


注意: linekedlist 编码的列表对象再地城的双端链表结构中包含了多个字符串对象,字符串对象是redis五中类型的对象中唯一一种会被其他4中类型对象嵌套的对象

编码转换

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

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

这两个值可以在配置文件中进行修改:

  • list-max-ziplist-value
  • list-max-ziplist-entries

哈希对象

底层实现

  • zipList
    当有新的键值对要加入哈希对象时,程序会先姜保存了键的压缩列表节点推入到压缩列表表尾,然后再将保存了值的压缩列表节点推入压缩列表结尾



-hashTable


编码转换

  • 哈希对象保存所有键值对的键和值字符串长度不小于64字节
  • 哈希对象保存的键值对数量小于512个
    不满足这两个条件,哈希对象使用hashtable编码

集合对象

底层实现

  • intset


  • hashtable


编码转换

  • 集合对象保存所有元素都是整数值
  • 集合对象保存的元素数量不超过512个
    不满足两个条件的集合对象要使用hashTable

有序集合对象

底层实现

  • ziplist
    有序集合对象使用ziplist实现时,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,而第二个元素保存元素的分值.



  • skiplist
    skiplist编码的有序集合对象使用zset结构作为底层实现.

/*
 * 有序集合
 */
typedef struct zset {

    // 字典,键为成员,值为分值
    // 用于支持 O(1) 复杂度的按成员取分值操作
    dict *dict;

    // 跳跃表,按分值排序成员
    // 用于支持平均复杂度为 O(log N) 的按分值定位成员操作
    // 以及范围操作
    zskiplist *zsl;

} zset;

zset结构中,跳跃表按照分值从小到大保存了所有集合的元素
zset结构中,dict字典为有序结合创建了一个从成员到分值的映射,字典的键保存了元素的成员,字典的值,保存了元素的分值
两种数据结构,通过指针来共享相同的元素成员和分值,不会浪费额外的内存.

注意: 图中为了方便展示,显示了各个元素的成员和分值,实际中,字典和跳跃表会共享元素的成员和分值

编码和转换

  • 有序集合保存的元素数量小于128个
  • 有序集合保存的所有元素成员长度小于64字节

对象的内存回收

Redis使用引用计数来实现内存回收机制

  • 创建新对象时,引用计数的值会初始化为1
  • 当对象被新程序使用时,引用计数j+1
  • 当不被y9ige程序使用时,引用 -1
  • 当引用计数为0 时,会被释放

对象共享

Redis会在初始化服务器时,创建一万个字符串对象,这些对象包含了从0到9999的所有整数值,服务器使用这些对象时,服务器会共享这些对象,而不是创建新的

对象空转时长

对象的lru属性,记录了对象最后一次被命令访问的时间
服务器打开了Maxmemory选项,并且服务器用于回事欧内存的算法为volatile-lru或者allkeys-lru,那么当服务器占用的内存超过了maxmemory选项所设置的上限值,空转时长较高的那部分键会被优先释放

总结

  • redis 有五种对象
    • 字符串对象
      实现方式: int, embstr, raw
    • 列表对象
      实现方式: ziplist,linkedlist
    • 哈希对象
      实现方式: ziplist,hashtable
    • 集合对象
      实现方式: intzet,hashtable
    • 有序集合对象
      实现方式: ziplist,zset-{hashtable,skiplist}

相关文章

  • redis对象之列表对象

    承接上文redis对象之字符串对象 参考文献:黄健宏《Redis设计与实现》 前言 列表对象是redis对象系统中...

  • redis笔记:对象

    本人博客同步发表,排版更佳 对象的类型 redis中的对象包括: 字符串对象 REDIS_STRING 列表对象 ...

  • redis中的对象

    redis的对象包含5种对象: 字符串对象 列表对象 哈希对象 集合对象 有序集合对象 redis对象的好处 针对...

  • Redis中的对象

    Redis中的每个对象都由一个redisObject结构表示,该结构中和保存数据有关的三个属性分别是type、en...

  • redis中的对象

    前言 在上一篇关于redis的文章中,我们分析了redis用到的主要的数据结构,但是redis并没有直接使用这些数...

  • redis zset内部实现

    Redis对象Redis对象由redisObject结构体表示。 Redis中的每个键值对的键和值都是一个redi...

  • Redis' strings

    Redis字符串基本操作命令 底层实现 Redis中,字符串对象是一个基础对象,所有键值均是字符串对象。Redis...

  • Redis 5种数据类型与11种编码方式

    1,redis核心对象结构 1)Redis object对象的数据结构,定义在src/server.h中。 2)c...

  • 【译】StackExchange.Redis中文使用文档--基本

    基本使用 StackExchange.Redis 中核心对象是在 StackExchange.Redis 命名空间...

  • redis对象实现

    redis对象 Redis 使用对象来表示数据库中的键和值, 每次当我们在 Redis 的数据库中新创建一个键值对...

网友评论

    本文标题:redis中的对象

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