SDS 的定义动态字符串的结构:/** 保存字符串对象的结构*/struct sdshdr {// buf 中已占用空间的长度int len;// buf 中剩余可用空间的长度int free;// 数据空间char buf[];};SDS长这样:

文章插图
SDS示例
- len 变量,用于记录buf 中已经 使用的空间长度 (这里指出Redis的长度为5);
- free 变量,用于记录buf修改后的还有 空余的空间,一般初次分配空间的时候,是没有空余的,在对字符串修改的时候,就会有剩余空间出现;
- buf 字符数组,用来记录 我们的字符串 (记录Redis)
这样做在获取字符串长度的时候,字符串扩展等操作的时候 效率比较低。C语言用这种 简单 的字符串表示方式,但是并不能满足Redis对字符串在安全性、效率以及功能方面的要求:
获取字符串长度(SDS O(1)/C 字符串 O(n))“
和C 字符串不同,SDS的数据结构中,有专门用于 保存字符串长度 的变量,我们可以通过获取len属性的值,如下图的,直接知道字符串长度:

文章插图
”
杜绝缓冲区溢出C 字符串是不会记录字符串长度的,除了获取的时候复杂度高以外,还容易导致缓冲区溢出 。我们现在假设程序中有两个在内存中 紧邻着的字符串s1和s2,其中s1保存了字符串“ redis ”,而s2 则保存了字符串“ MongoDb ”:

文章插图
如果我们现在将s1的内容修改为 redis cluster,但是我又忘了重新为 s1分配足够的空间,这时候就会出现以下问题:

文章插图
我们可以看到,原本s2中的内容已经 被S1的给占领 了,s2现在是cluster,而不是“Mongodb” 。Redis 中SDS 的 空间分配策略 完全 杜绝 了发生缓冲区溢出的可能性:
“
我们需要对一个SDS进行修改的时候,redis会在执行 拼接操作 之前,预先检查给定SDS空间是否是足够的,如果不够,会先 拓展SDS 的空间,然后再执行拼接操作;
”

文章插图

文章插图
减少修改字符串时带来的内存重分配次数C字符串在进行字符串的扩充和收缩的时候,都常常会面临着 内存空间 重新分配的问题 。
- 字符串拼接会产生字符串的内存空间的 扩充,在拼接的过程中,原来的字符串的大小很可能 小于 拼接后的字符串的大小,那么这样的话,就会导致一旦 忘记申请 分配空间,就会导致内存的溢出 。
- 字符串在进行收缩的时候,内存空间会 相应的收缩,而如果在进行字符串的切割的时候,没有对内存的空间进行一个重新分配,那么这部分多出来的空间就成为了内存泄露 。*

文章插图

文章插图
因为在上一次修改字符串的时候已经拓展了空间,再次进行修改字符串的时候你会发现空间是足够使用,因此就不要进行空间拓展了 。

文章插图
通过这种 预分配策略,SDS将连续增长N次字符串所需的 内存重分配次数 从必定N次会降低为最多N次
惰性空间释放我们在观察SDS的结构的时候,可以看到里面有free属性,是用于 记录空余空间 的 。我们除了在拓展字符串的时候会使用到free来进行记录空余空间以外,在对字符串进行收缩的时候,我们也可以使用free 属性来进行 记录剩余空间,这样做的好处就是避免下次对字符串进行再次修改的时候,我们 再对 字符串的空间进行拓展 。
“
推荐阅读
- 李自成灭亡的真正原因,李自成失败的根本原因是什么
- 朱元璋杀李善长的真正原因是什么?,朱元璋为何杀李善长全家
- OceanBase开源,11张图带你了解分布式数据库的核心知识
- reflector 带你彻底搞懂MyBatis的底层实现之反射工具箱
- 真正降血压的茶,降血压喝什么茶最好
- 一篇文章带你搞懂Python中的类
- 软件测试知识点3大场景带你了解单元测试
- 秦始皇不立皇后的真正原因,秦始皇为什么终身不立后
- 历史上真正的刘彧,刘彧是不是昏君
- 乾隆身世之谜-到底谁是弘历生母-乾隆果真是汉女所生-?乾隆与其母的真正关系_1
