redis 数据结构

一 字符串

底层使用SDS的数据结构来保存字符串,而不是用C语言中的字符串。SDS即simple dynamic string,结构如下:


sdsstr数据结构及示例
  • len: 已经使用的字段的长度
  • free: 未使用的字段的长度
  • buf: 字节数组

而C语言中的字符串,就是一个单纯的以\0结尾的数组,

与C语言中的字符串相比,SDS有以下几点优势:

  1. 计算长度的时间复杂度为o(1),而不是C字符串的o(n)
    C字符串的格式就是一个以\0结束的数组,如果要获取长度需要遍历,而sds使用len保存了这个数据。

  2. 不用考虑内存溢出等问题,内部已经封装好了
    C字符串扩展字符串时要自己分配内存,否则内存会溢出,而sds已经对长度的检测做了封装了。

  3. 扩展字符串或者缩减字符串不需要重新分配内存
    C字符串中扩展和缩减字符串都需要重新分配内存,但是sds不需要,因为它有未使用的字节长度,所以其实是可以伸缩的。

  4. 二进制安全
    C字符串以\0结尾,因此不能保存内部可能出现\0的二进制数据。虽然sds也是\0结尾的,但是实际读取时会依赖于长度len来读取,不需要担心\0的问题。

C字符串与SDS的区别

二 链表

redis中的链表它就是一个普通的双向链表,没有什么花里胡哨的操作,列表的结构体叫list,列表节点的结构体叫listNode

链表

dup, free, match 三个操作链表相关的函数

三 hash表(字典)

3.1 结构

redis中的数据库(也就是键与值的对应关系)和散列表都是基于字典来实现的
底层结构与Java中的HashMap类似,桶链结构:


redis中的字典

dictht即字典对应的结构体名称,而dictEntry是字典中中链表的结构体名称

  • table: dictEntry数组,实际保存数据
  • size: dictEntry的长度
  • sizemask: 总是为size - 1,用于把节点映射到桶的下标
  • used: 实际保存的数据量

hash算法:murmurhash

3.2 扩容

触发条件,以下两个任意满足一个:

  • 负载因子 >= 1 且 没有正在执行BGSAVE或者BGREWRITEAOP命令
  • 负载因子 >= 5

扩容方式:每次都取比当前数据量used*2大的最小的2的整数次幂

3.3渐渐式 rehash

扩容时不会立即把数据rehash到新的hash表中去,而是在每次操作对应数据时才rehash那一项

四 跳跃表

跳跃表的基本内容

redis中的跳跃表


redis中的跳跃表

感觉跟一个普通的跳跃表没什么区别

五 整数集合

当redis中集合只包含整数数据时,会使用整数集合来保存


redis中的整数集合

集合的元素类型会依据元素最大绝对值来使用long,int,short,或者byte

六 压缩列表ziplist

ziplist分为 头-体 两部分,头部数据包含:

  • zlbytes: 整个结构体占用的空间
  • zltail: 到最后一个元素的偏移量,方便从后面查找
  • zllen: 元素的数量

中间元素的数据结构,有四个字段:

  • 前一个元素的大小:方便倒顺查找
  • 当前元素的编码类型
  • 当前元素的大小:通过这个值可以定位到下一个元素的位置
  • 当前元素的内容

此外ziplist用一个单字节的值zlend = 255来标记结尾

ziplist

七 redis中各种数据类型对应的数据结构

7.1 对象类型与编码

redis中使用redisObject保存所有对象的数据:

typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS;
    int refcount;
    void *ptr;
} robj;
  • type: 对象数据类型,只能取redis支持的五种数据类型
  • encoding: 对象的数据结构,也就是上面说的那些数据结构
  • refcount: redis使用引用记数法做内存回收
  • ptr: 数据地址

例如执行SET msg "hello world"命令后,redis底层将多了两个redisObject对象,一个对象保存了键的数据,另一个保存了值的数据,而type字段标记了这两个对象保存的数据类型。

7.2 字符串类型对应的数据结构

redis中字符串类型可以使用以下三种数据结构保存:

  • int: 数字类型。如果字符串值实际上是一个数字,且能用long表示,则使用数字类型。
  • embstr: 也就是上面说的sds字符串。如果字符串的值的长度 <= 32,则使用这种类型。
  • raw: 也是上面说的sds字符串。如果字符串值的长度 > 32,则使用这种类型。

embstrraw的区别是:embstr会为redisoObject和sds字符串一次性分配内存空间,而raw则会分两次分别为它们分配内存空间。也就是说embstr的redisObject和sds两个对象在物理上是连续的,而raw不是。

7.3 列表类型对应的数据结构

  • ziplist: 当列表中元素的个数 <= 512,并且每个元素的长度 <= 64时,使用ziplist
  • linkedlist: 当元素个数 > 512 或者至少有一个长度 > 64 的元素时,使用linkedlist

64和512这两个值可以使用list-max-ziplist-value和list-max-ziplist-entries来设置

7.4 散列表类型的数据结构

  • ziplist: 所有键值对的键和值的长度都 <= 64,并且键值对个数 <= 512
  • hashtable: 也就是字典,不满足上面的条件时使用字典

使用ziplist时,底层是按照 键 - 值 - 键 - 值 - 键 - 值这样交替摆放来实现的

这里的64和512这两个值可以使用hash-max-ziplist-value和hash-max-ziplist-entries来设置

7.5 集合类型的数据结构

  • intset: 集合中的元素都是整数,且个数 <= 512
  • hashtable: 不满足上述条件时使用hashtable

512这个上限可使用set-max-intset-entries 来修改

7.6 有序集合的数据结构

  • ziplist: 集合中元素个数 <= 128 且每个元素的长度 <= 64
  • skiplist: 不满足上述条件后使用

使用ziplist时的结构:值-分数-值-分数-值-分数
如果使用的是skiplist,还会再使用字典保存元素与分数的对应关系

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