redis源码之动态字符串sds

未完待续…

简单动态字符串sds

1.简介:

在Redis 里面, C 字符串只会作为字符串字面量用在一些无须对字符串值进行修改的地方,比如打印日志;如果需要可以被修改的字符串,则用sds表示字符串值。

2.sds应用

1.保存数据库中的字符串值
2.被用作缓冲区:AOF 缓冲区,客户端状态中的输人缓冲区。

3.sds定义

// sdshdr 保存字符串对象的结构
struct sdshdr {

    int len;// buf 中已占用空间的长度

    int free;// buf 中剩余可用空间的长度

    char buf[];// 数据空间
};

带有未使用空间的sds 示例

4.sds与C字符串

1.SDS 遵循 C 字符串以空字符结尾的惯例;因此可以直接重用一部分 C 字符串函数库里面的函数。
2.常数复杂度获取字符串长度(len);因为 SDS 在 len 属性中记录了 SDS 本身的长度, 获取一个 SDS 长度的复杂度仅为 O(1),这确保了获取字符串长度的工作不会成为 Redis 的性能瓶颈。
3.杜绝缓冲区溢出(len);当 SDS API 需要对 SDS 进行修改时, API 会先检查 SDS 的空间是否满足修改所需的要求,如果不满足的话, API 会自动将 SDS 的空间扩展至执行修改所需的大小。
4.减少修改字符串时带来的内存重分配次数(free);通过未使用空间, SDS 实现了空间预分配和惰性空间释放两种优化策略。
(1)对 SDS 进行修改时,内存不够:如果SDS 的len将小于 1 MB ,那么程序分配和 len 属性同样大小的未使用空间 ;如果SDS 的len将大于 1 MB ,就分配 1 MB 的未使用空间。
(2)当 SDS 的 API 需要缩短 SDS 保存的字符串时, 程序并不立即使用内存重分配来回收缩短后多出来的字节, 而是使用 free 属性将这些字节的数量记录起来,并等待将来使用。
5.二进制安全
C 字符串中的字符必须符合某种编码(比如 ASCII), 并且除了字符串的末尾之外, 字符串里面不能包含空字符, 否则最先被程序读入的空字符将被误认为是字符串结尾 —— 这些限制使得 C 字符串只能保存文本数据, 而不能保存像图片、音频、视频、压缩文件这样的二进制数据。
虽然数据库一般用于保存文本数据, 但使用数据库来保存二进制数据的场景也不少见,因此, 为了确保 Redis 可以适用于各种不同的使用场景,SDS 的 API 都是二进制安全,所有 SDS API 都会以处理二进制的方式来处理 SDS 存放在 buf 数组里的数据, —— 数据在写入时是什么样的, 它被读取时就是什么样。
比如说, 使用 SDS 来保存中间含有’/0’的特殊数据格式就没有任何问题, 因为 SDS 使用 len 属性的值而不是空字符来判断字符串是否结束!

C字符串 SDS
可以使用所有 < string.h > 库中的函数 可以使用一部分 < string.h > 库中的函数。
获取字符串长度的复杂度为 O(N) 获取字符串长度的复杂度为 O(1)
API 是不安全的,可能会造成缓冲区溢出 API 是安全的,不会造成缓冲区溢出
修改字符串长度 N 次必然需要执行 N 次内存重分配 修改字符串长度 N 次最多需要执行 N 次内存重分配
只能保存文本数据 可以保存文本或者二进制数据

猜你喜欢

转载自blog.csdn.net/qiangzhenyi1207/article/details/80346998