redis五种数据类型内部构造

1、String

1、实现方式:

1、RAW编码方式:默认的,redisObject指针指向SDS

2、EMBSTR编码方式:redisObject和SDS形成数组

3、INT编码方式:直接用redisObject指针存储,指针是无符号的8位

StringRedis中最常见的数据存储类型:

1、 基本编码 方式是 RAW ,基于简单动态字符串( SDS )实现, 存储上限 512mb
2、 如果存储的 SDS 长度小于44字 节,则会采用 EMBSTR 编码,此时 object head与SDS是一段连续空间 申请内存 只需 调用一次 内存分配函数,效率更高。
3、 如果 存储 字符串 整数值 ,并且大小在 LONG_MAX范围 内,则会采用 INT 编码:直接将数据保存在 RedisObject ptr 指针位置(刚好 8 字节),不再需要 SDS 了。

1、下图是RAW编码方式:

基本编码 方式是 RAW ,基于简单动态字符串( SDS )实现, 存储上限 512mb

2、下图是EMBSTR编码方式

如果存储的SDS长度小于44字节,则会采用EMBSTR编码,此时object headSDS是一段连续空间。申请内存时只需要调用一次内存分配函数,效率更高。

 3、下图是INT编码方式

如果存储的字符串是整数值,并且大小在LONG_MAX范围内,则会采用INT编码:直接将数据保存在RedisObjectptr指针位置(刚好8字节),不再需要SDS了。

 总结:

可以看到String具有的三种转换形式

 测试

 2、List

2、实现方式:

1、3.2版本之前,ZipListLinkedList来实现List

2、3.2版本之后,QuickList实现

RedisList类型可以从首、尾操作列表中的元素:

哪一个数据结构能满足上述特征?

LinkedList :普通链表,可以从双端访问, 内存占用较高 ,内存 碎片较多
ZipList :压缩列表,可以从双端访问, 内存占用低 ,存储 上限低
QuickList LinkedList + ZipList ,可以从双端访问,内存 占用较低 ,包含多个 ZipList 存储上限高

RedisList结构类似一个双端链表,可以从首、尾操作列表中的元素:

3.2版本之前Redis采用ZipListLinkedList来实现List,当元素数量小于512并且元素大小小于64字节时采用ZipList编码超过则采用LinkedList编码

3.2版本之后Redis统一采用QuickList来实现List

 

 

 3、Set

3、实现方式:

1、Dict实现,value都存储null

2、如果都是整数,那么用Inset结构

SetRedis中的单列集合,满足下列特点:

1、 不保证有序性
2、 保证 元素唯一 ( 可以判断元素是否存在 )
3、 求交集、并集、差集

可以看出,Set对查询元素的效率要求非常高,思考一下,什么样的数据结构可以满足?

1、 HashTable ,也就是 Redis 中的 Dict ,不过 Dict 是双列集合(可以存键、值对)
2、 为了查询效率和唯一性, set 采用 HT 编码( Dict )。 Dict 中的 key 用来存储元素, value统一为null。
3、 当存储的 所有数据 是整数 ,并且 元素数量 不超过 set-max-intset-entries时 Set 会采用 IntSet编码 ,以节省内存。
源码:
1、下图解释传入的数据不同set底层创建的方式也是不同的
2、下面是添加元素

 

 展示

 

4、ZSet

4、实现方式:

1、SkipList(有序)和HT(键值查找)结合构成

2、ZipList,两个entry构成一个,ele为键,score为值

ZSet也就是SortedSet,其中每一个元素都需要指定一个score值member值

1、可以根据score值排序

2、member必须唯一

3、可以根据member查询分数

 

因此,zset底层数据结构必须满足键值存储、键必须唯一、可排序这几个需求。之前学习的哪种编码结构可以满足?

1、 SkipList 可以排序 ,并且可以同时 存储score和ele值 member
2、 HT Dict 可以 键值存储 ,并且可以 根据key找value,key==ele,value==score

 

 

 源码分析

元素数量不多时,HT和SkipList优势不明显,而且更耗内存。因此zset还会采用ZipList结构来节省内存,不过需要同时满足两个条件

元素数量小于zset_max_ziplist_entries,默认值128

每个元素小于zset_max_ziplist_value字节,默认值64

ziplist本身没有排序功能,而且没有键值对的概念,因此需要zset通过编码实现

1、ZipList连续内存,因此score和element紧挨在一起的两个entry element在前score在后2、score越小接近队首score越大越接近队尾,按照score值升序排列

从下面代码可以看到

1、zset实现的两种方式

 2、下面的是添加Zset的方法

 

 5、Hash

5、实现方式:

本质和zset是一样的

1、直接用dict实现,去除跳表

2、使用ZipList实现

Hash结构与Redis中的Zset非常类似:

1、 都是键值存储
2、 都需求根据键获取值
3、 键必须唯一

区别如下:

1、zset键是member值是scorehash的键和值都是任意值

2、zset要根据score排序hash无需排序

因此,Hash底层采用的编码与Zset也基本一致,只需要把排序有关的SkipList去掉即可:

 因此,Hash底层采用的编码与Zset也基本一致,只需要把排序有关的SkipList去掉即可:

1、Hash结构默认采用ZipList编码,用以节省内存。 ZipList中相邻的两个entry 分别保存fieldvalue

2、数据量较大时,Hash结构会转为HT编码,也就是Dict,触发条件有两个:

ZipList中的元素数量超过hash-max-ziplist-entries(默认512

ZipList中的任意entry大小超过hash-max-ziplist-value(默认64字节

hash对应的两种结构

 

 

 

 源码展示

 

 

猜你喜欢

转载自blog.csdn.net/qq_36437693/article/details/127187643
今日推荐