redis底层数据结构1——简单动态字符串、链表、字典

简单动态字符串

为了提高效率,redis 以空间换时间为代价,创建了一种简单动态字符串(simple dynamic string,SDS)。
在redis里面,C字符串只会作为字符串字面量用在无需对字符串值进行修改的地方,比如日志打印。其他地方,都使用SDS。

SDS 的结构

结构如下。为了兼容C字符串,直接重用C字符串函数库里面的部分函数,SDS 依旧使用 N+1 结构,即字符串以 ‘\0’ 结束。
在这里插入图片描述

SDS 和C字符串的区别(优势)

常数复杂度获取字符串长度

C字符串获取字符串长度,需要遍历计数,直至遇到代表字符串结尾的空字符为止。这个操作的复杂度为O(N)。
SDS 本身就有一个 len 属性,可以直接访问 len 属性,所以时间复杂度是O(1)。设置和更新 SDS 长度的工作是由 SDS 的API自动完成的。

杜绝缓冲区溢出

使用 C 字符串,经常会遇到内存溢出的情况。
SDS 字符串增加了检测机制,可以杜绝缓冲区溢出的可能性。当SDS API需要对 SDS 进行修改时,API 会先检查 SDS 的空间是否满足修改的需求,如果不满足,会先自动扩展空间,然后再执行修改。,

减少修改字符串时带来的内存分配次数

空间预分配

当SDS API需要对 SDS 进行修改,并且需要对空间扩展时,程序不仅会分配修改所必要的时间,还会分配额外的未使用空间。可以避免每次修改都进行分配。
分配公式如下:

  • 如果对 SDS 修改后,SDS的长度小于 1MB,那么程序将额外分配和 len 属性同样的未使用空间。假设修改后,SDS 的 len 变为13字节,那么 SDS 的实际长度将变为 13+13+1=27字节。
  • 如果 SDS 修改之后,长度大于等于 1MB,那么程序会分配 1MB 的未使用空间。
惰性空间释放

当 SDS 保存的字符串需要缩短时,不立刻使用内存重分配来回收多余的空间,而是通过增加 free 属性,将这些字节记录起来。在有需要时才真正释放。

二进制安全

SDS 的 API都是二进制安全的,数据在写入和读取时,不会有任何变化,可以用来保存任意格式的数据。

兼容部分C字符串函数

末尾设置空结束符,兼容C字符串,直接重用C字符串函数库里面的部分函数

链表

由于 C 语言没有链表,所以 redis 实现了自己的链表。
链表呗广泛用于实现 Redis 的各种功能,比如列表键、发布与订阅、慢查询、监视器等。

链表结构

redis 链表由链表和链表节点构成。
在这里插入图片描述
由图可知,链表的特性可以总结如下:

  • 双端:链表节点有 prev 和 next 指针,获取某个前直接点和后置节点的复杂度都是O(1)。
  • 无环:表头节点的 prev 和表尾结点的 next 指针都执行 NULL,对链表的访问以 NULL 为终点。
  • 带表头指针和表尾指针。
  • 带链表长度计数器:对整个链表中的节点进行计数。
  • 多态:可以通过 list 结构的 dup、free、match三个属性为节点设置类型特定函数。

字典

字典是一种保存键值对的数据结构,类似Map。
字典呗广泛用于实现 Redis 的各种功能,包括数据库和哈希键(字段比较多的情况使用)。

结构实现

字典的结构包含字典头、哈希表和哈希表节点,如下如所示:
在这里插入图片描述

哈希表和哈希节点的定义如下图:
在这里插入图片描述
字典的定义如下:
在这里插入图片描述
ht是一个包含两个哈希表的数组,一般情况下,只是用 ht[0] 哈希表,ht[1] 哈希表只会在进行 rehash 时使用。rehashids 记录了rehash的进度,如果目前不是正在进行 rehash,其值为-1。

哈希算法

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

解决键冲突

当有两个或以上的键被分配到了同一个索引上,就出现了冲突。Redis使用链地址法来解决冲突,每个哈希表节点都有一个 next 指针。同一索引下的多个节点可以使用单向链表连接起来。
因为是单向链表,没有指向表尾的指针,所以为了速度考虑,采用首插法。(???有疑问,应该是会和每个key比对,如果都不一样才会插入吧。既然已经遍历比对了,那尾插首插,速度不一样吗???)

rehash

哈希表的负载因子如下:

	负载因子 = 哈希表以保存节点数量 / 哈希表的大小

哈希表扩展和述所的条件

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

rehash 的过程

在这里插入图片描述

渐进式 rehash

Redis 中的键值对可以达到千万乃至亿级,所以就不能一次性地完成 rehash,需要分多次、渐进式地完成。
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值