Redis源码

一、Redis数据结构:

SDS

SDS(动态字符串)包含字符数组buf[],字符数组现有长度len,字符数组分配空间的长度alloc,SDS类型flags。
总结:
1、C语言中使用char*实现字符串的不足,主要是因为使用“\0”表示字符串结束,操作时需遍历字符串,效率不高,并且无法完整表示包含“\0”的数据,因而这就无法满足Redis的需求。
2、Redis专门设计了SDS数据结构,在字符数组的基础上,增加了字符数组长度和分配空间大小等元数据。这样一来,需要基于字符串长度进行的追加、复制、比较等操作,就可以直接读取元数据,效率也就提升了。而且,SDS不通过字符串中的“\0”字符判断字符串结束,而是直接将其作为二进制数据处理,可以用来保存图片等二进制数据。
3、SDS中是通过设计不同SDS类型来表示不同大小的字符串,并使用attribute ((packed))这个编程小技巧,来实现紧凑型内存布局,达到节省内存的目的。

Hash

哈希冲突:Redis采用了链式哈希,在不扩容哈希表的前提下,将具有相同哈希值的数据链接起来,以便这些数据在表中仍然可以被查询到。
(但随着链表长度的增加,Hash表在一个位置上查询哈希项的耗时就会增加,所以引用了rehash)
Rehash指扩大Hash表空间,用一个hash表(ht[0])复制到另一个hash表(ht[1]),然后将ht[1]设置为ht[0]
rehash开销:Redis实现了渐进式rehash设计,进而缓解了rehash操作带来的额外开销对系统的性能影响。
1、 rehash扩容扩多大?
默认是原来空间的2倍
2、为什么有rehash开销?(为什么要实现渐进式rehash?)
Hash表执行rehash时,需将键从原来的位置拷贝到新的位置。而在键拷贝时,由于Redis主线程无法执行其他请求,所以键拷贝会阻塞主线程,这样就会产生rehash开销。
3、渐进式rehash如何实现?
Redis并不会一次性把当前Hash表中的所有键,都拷贝到新位置,而是会分批拷贝,每次的键拷贝只拷贝Hash表中一个bucket中的哈希项
4、什么时候触发rehash?
hash表承载的元素个数超过了它本身的大小或者hash表承载的元素个数是它本身大小的5倍

Sorted Set

Sorted Set采用跳表和哈希表
跳表高效支持范围查询、哈希表高效支持单点查询。
跳表是一个多层的有序链表,每一层也是由多个结点通过指针连接起来的。

Ziplist、quicklist、Listpack

Ziplist不足:ziplist中元素个数多了,它的查找效率就会降低。而且如果在ziplist里新增或修改数据,ziplist占用的内存空间还需要重新分配;更糟糕的是,ziplist新增某个元素或修改某个元素时,可能会导致后续元素的prevlen占用空间都发生变化,从而引起连锁更新问题,导致每个元素的空间都要重新分配,这就会导致ziplist的访问性能下降。
Quicklist:quicklist结构在ziplist基础上,使用链表将ziplist串联起来,链表的每个元素就是一个ziplist。这种设计减少了数据插入时内存空间的重新分配,以及内存数据的拷贝。同时,quicklist限制了每个节点上ziplist的大小,一旦一个ziplist过大,就会采用新增quicklist节点的方法。
Listpack:该结构沿用了ziplist紧凑型的内存布局,把每个元素都紧挨着放置。listpack中每个列表项不再包含前一项的长度了,因此当某个列表项中的数据发生变化,导致列表项长度变化时,其他列表项的长度是不会受影响的,因而这就避免了ziplist面临的连锁更新问题。

Redis数据结构

链表

Redis链表为双向无环链表
Redis中的list是个双向无环链表,并使用了一个list来持有链表
双向:链表节点带有前驱、后继指针获取某个节点的前驱、后继节点的时间复杂度为0(1)。
无环: 链表为非循环链表表头节点的前驱指针和表尾节点的后继指针都指向NULL,对链表的访问以NULL为终点。
带表头指针和表尾指针:通过list结构中的head和tail指针,获取表头和表尾节点的时间复杂度都为O(1)。
带链表长度计数器:通过list结构的len属性获取节点数量的时间复杂度为O(1)。
多态:链表节点使用void*指针保存节点的值,并且可以通过list结构的dup、free、match三个属性为节点值设置类型特定函数,所以链表可以用来保存各种不同类型的值。

字典

Redis字典使用散列表最为底层实现,一个散列表里面有多个散列表节点,每个散列表节点就保存了字典中的一个键值对。
Redis如何解决散列冲突
链式哈希和rehash
链式哈希:在不扩容哈希表的前提下,将具有相同哈希值的数据链接起来,以便这些数据在表中仍然可以被查询到。
Rehash:用一个hash表(ht[0])复制到另一个hash表(ht[1]),然后将ht[1]设置为ht[0]

跳跃表

跳跃表基于链表,每层都是有序双向链表(有前进指针和后退指针)
跳跃表以空间换时间的方式提升了查找速度
Redis有序集合在节点元素较大或者元素数量较多时使用跳跃表实现
Redis的跳跃表实现由 zskiplist和 zskiplistnode两个结构组成,其中 zskiplist用于保存跳跃表信息(比如表头节点、表尾节点、长度),而zskiplistnode则用于表示跳跃表节点
Redis每个跳跃表节点的层高都是1至32之间的随机数
在同一个跳跃表中,多个节点可以包含相同的分值,但每个节点的成员对象必须是唯一的跳跃表中的节点按照分值大小进行排序,当分值相同时,节点按照成员对象的大小进行排序。

整数集合

整数集合是Redis自己设计的一种存储结构,集合键的底层实现之一。
整数集合的底层实现为数组,这个数组以有序、无重复的方式保存集合元素,在有需要时,程序会根据新添加元素的类型,改变这个数组的类型。
升级操作为整数集合带来了操作上的灵活性,并且尽可能地节约了内存。
整数集合只支持升级操作,不支持降级操作
升级指的是存储一个int64数据类型的元素,将数组中int32的元素全部都变成int64位数据类型

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

推荐阅读更多精彩内容