Redis设计与实现 数据结构与对象

1、简单动态字符串(SDS)

1、1 总览

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
SDS的作用不止于此,它在redis中也被用作缓冲区,如AOF中的AOF缓冲区,客户端的输入缓冲区。

1、2 SDS数据结构

在这里插入图片描述
示例:
在这里插入图片描述

1、3 SDS与C语言字符串的区别

  1. 获取字符串长度的时间复杂度
    SDS为O(1),因为SDS的数据结构维护了len变量;
    C语言字符串(后续称之为C串)为O(N),因为要遍历整个串。

  2. 杜绝缓冲区溢出
    C语言的字符串拼接函数
    在这里插入图片描述
    在C中,使用这个函数可能会缓冲区溢出,因为拼接之后原串的长度会边长,会覆盖后面一些字节空间的内容,即溢出。
    而在SDS中,也有类似的函数,叫sdscat,它不会溢出,因为在拼接之前会预先申请足够的空间

  3. 修改字符串时的内存重分配次数
    在C中,每次增加或者缩短一个字符串的时候,都需要对保存该C串的字符数组重新进行内存分配。若不分配,当增长C串时,会缓存溢出;在缩短C串时,会内存泄漏
    而在SDS中,由于空间预分配惰性空间释放这两个特点,可以减少内存重新分配次数。
    空间预分配:在增长字符串时,SDS的API会申请额外的空间。
    惰性空间释放:在缩短字符串时,SDS不会立即释放未使用的空间,而是用free关键字来记录未使用的空间。

  4. 二进制安全
    C串只能保存文本,不能保存二进制文件,因为二进制文件中可能包含’\0’。
    而SDS可以,因为在SDS的buf数组中保存的不是字符,而是二进制数据(暂不理解),因此在redis中存入什么,就能原封不动的读出什么。
    在这里插入图片描述

2、redis的链表

数据结构:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
例子:
在这里插入图片描述
特点:
在这里插入图片描述

3、字典

redis的字典可以用来保存数对键值对,如下图所示
在这里插入图片描述

3、1数据结构

redis的字典基于hash表,由于C语言没有实现hash表,所以redis自己实现了,其结构如下:
在这里插入图片描述
上图是redis的hash表的数据结构示意图,而redis的字典的数据结构和示意图如下:
在这里插入图片描述
在这里插入图片描述
下图是一个没有在rehash状态下的字典的示意图:
在这里插入图片描述

3、2hash算法

计算dictEntry的索引的方法:hash(key) & (size - 1)
解决hash冲突:链地址法
负载因子的计算方法:
在这里插入图片描述
当负载因子小于0.1时,程序自动收缩哈希表;
在这里插入图片描述
在执行BGSAVE或者BGREWRITEAOF命令的时候,为了防止rehash的发生,redis提高了负载因子的阈值
在这里插入图片描述

3、3渐进式hash

在这里插入图片描述
在这里插入图片描述

4、跳跃表-有序集合

https://www.cnblogs.com/hunternet/p/11248192.html

5、整数集合

在这里插入图片描述

5、1 整型的升级

在这里插入图片描述
注:全部元素都要升级,时间复杂度是O(n)
往redis的整数集合里面添加一个整数,时间复杂度是O(n),即最坏情况。
升级之后不会降级。

6、 压缩列表

https://www.cnblogs.com/hunternet/p/11306690.html

7、对象

7、1 数据结构

在这里插入图片描述
在这里插入图片描述

7、2 redis中的对象

7、2、1 字符串对象

如果一个字符串对象保存的是整数值,并且这个整数值可以用long来保存,那么redis会用int来encoding该字符串对象,并且将对象头中的ptr由void*改为long。
在这里插入图片描述
在这里插入图片描述
如果保存的是普通的串:
长度大于32字节的,用SDS来保存这个值,编码方式为raw
否则,编码方式为embstr
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
long double类型的浮点数在redis中也是用字符串来保存的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
int可以转为raw,比如向数值类型的字符串append一些字符。
embstr不可修改,当需要修改时,会转成raw编码

7、2、2 列表对象

列表对象的编码可以是ziplist和linkedList
在这里插入图片描述
当以ziplist编码的列表,不满足以上条件的时候,会由ziplist编码转换成linkedList编码

7、2、3 哈希对象

hash对象的编码可以是ziplist和hashtable,用ziplist编码的hash对象如图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ziplist可以转成hashtable

7、2、4 集合对象

编码可以是intset和hashtable
在这里插入图片描述
intset可以转成hashtable

7、2、5 有序集合

编码是ziplist和skiplist
在这里插入图片描述
为什么同时使用这两种编码方式呢?
其实有序集合单独使用字典或跳跃表其中一种数据结构都可以实现,但是这里使用两种数据结构组合起来,原因是假如我们单独使用 字典,虽然能以 O(1) 的时间复杂度查找成员的分值,但是因为字典是以无序的方式来保存集合元素,所以每次进行范围操作的时候都要进行排序;假如我们单独使用跳跃表来实现,虽然能执行范围操作,但是查找操作有 O(1)的复杂度变为了O(logN)。因此Redis使用了两种数据结构来共同实现有序集合。
在这里插入图片描述

7、3 内存回收

由于C语言没有内存回收功能,所以redis采用了基于引用计数的内存回收机制
在这里插入图片描述
在这里插入图片描述

7、4 对象共享

redis在启动时,会创建0-9999这些数值的字符串对象,当后续有创建这些对象时,只需要引用即可,无需新创建。大大节省内存。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值