redis中的对象

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}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348