42张图,带你真正搞懂redis数据类型的底层

思维导图:

42张图,带你真正搞懂redis数据类型的底层

文章插图
 
我是redis你好,我是 redis
一个叫Antirez的男人带我来到这个充满复杂的世界上 。
42张图,带你真正搞懂redis数据类型的底层

文章插图
 
聊到我的出生,那跟MySQL大哥脱不了关系呀,我是来帮助他的,所谓天降猛男redis就是我了,真想对他说:

我还没有来到这个世界上的时候,刚开始挺好的,互联网前期,咱们的用户请求也不多,主要是一些静态网站和小游戏,这 有啥难的,MYSQL大哥一个顶俩好吧 。但天有不测风云,历史不会停止步伐的 。用户请求的数据也随之暴涨,每天用户的 每一次请求 都变成了对它的一个又一个的 读写操作,MYSQL直呼“快杀了我吧”,每年的“618”或者过年买票的时候,都是MYSQL受苦受累的日子啊!

反思 问题 出现在哪里,MYSQL大哥开始头头分析起来,原来有一大半的用户请求tm都是 读操作,而且经常又是查一个东西,简直浪费我 磁盘IO 的时间 。后来我的爸爸突发奇想,你看看别人 CPU的缓存 是很快的呀,给数据库加个缓存就解决了呗,于是我就出生了!出生没几天,我就来给MYSQL大哥解决问题,效果也还不错,我们也成为了 好基友,常常手拉手在后端服务器中配合,大致如图:
42张图,带你真正搞懂redis数据类型的底层

文章插图
 
为了方便与内存对接,我支持好几种数据结构的存储:

String
Hash
List
Set
SortedSet
Bitmap
......

因为把MYSQL里 登记的数据 都放到我的内存里来,就不去执行慢如蜗牛的I/O操作,所以下次找我肯定比找MYSQL要 省去 不少的时间呢 。
可别小瞧这一个微小的操作,可帮MYSQL大哥减轻了不小的负担!我缓存的数据也逐渐增长,有
相当部分
的时间都给他挡住了用户请求,这下他可就清闲自在了!

那今天就给大家聊一聊,咱的看家本领,内存是如何 管 上面的数据类型的 。说着,我拿笔给大家 画 一张图:

42张图,带你真正搞懂redis数据类型的底层

文章插图
 
看看,我的肚子里用了一个redisObject对象来展示所有的 value和key。type就是value对象是 那种 数据类型,第二个encoding就是不同的数据类型在Redis内部是如何 放 的 。
譬如: type=String 则表示value存储的是一个普通字符串,那我推断出 encoding 可以是raw或者是int 。但是我稍加思索,哎,还要解释下 底层数据结构,你知道吗?底层的底层,你有了解过吗?跟着我摆起来哈 。
下面是各自对应的数据结构;
42张图,带你真正搞懂redis数据类型的底层

文章插图
 
可以看出来,有很多类型都是使用 两种结构,就像set在元素比较少的时候,且都是数字的情况下会用 整数列表,随着数据增加就变成 哈希表。但是我有一个比较大的疑问,这些类型都对应不同的数据结构,想想redis 整体的结构
是啥样的呢?再举个例子,现在有一个
key对应的value
是我们的list类型的,那就对应着上面的双向链表啊?那咱第一步就要找到这个key,就可找到双向链表了噻;
看看全局哈希表其实啊,我这里是有一个大的哈希表的,在 你们的眼 里可能就是类似的长数组,在它上面的每个空间,都可以看做一个哈希桶,长这样:
42张图,带你真正搞懂redis数据类型的底层

文章插图
 
每一个key经过我肚子里面的hash算法就会给你算出一个位置,怎么来算请看下面:
哈希算法:Redis计算哈希值和索引值方法如下:
//1、使用字典设置的哈希函数,计算键 key 的哈希值hash = dict->type->hashFunction(key);//2、使用哈希表的sizemask属性和第一步得到的哈希值,计算索引值index = hash & dict->ht[x].sizemask;那它就对应一个哈希桶呗 。壮士请注意,这个过程是很快的哈 。只有O(1)哦,这个过程咱就算出 内存地址,那你就直接去找就行了 。然后我们把这个key放到hash桶里面去 。记住啊壮士,这个桶里面 保存的是引用 哈,不是你的 那个对象(狗头)。就好比哈希桶里面保存的是key家的门牌号一样(实质内存地址),那我们就用了0(1)的复杂度就这样找到这个key 。,因为用key去查找value的时候,只需要在经过依次hash能马上找到哈希桶,就能定位到这个 键值对 的内存地址了 。


推荐阅读