第二章 简单动态字符串SDS

C语言中传统的字符串:以空字符结尾的字符数组,不可修改

Redis创建了一个新的简单动态字符串SDS,并作为Redis默认字符串表示,应用于一些字符串要求被修改的场景!

使用场景:
在Redis中,C字符串只作为字符串字面量,用在不需要改变字符串的场景,比如打印日志

当Redis不只是需要字符串字面量,而是可以被修改的字符串值,就可以SDS来表示字符串值;比如Redis的数据库里面,包含字符串的键值对在底层都是由SDS实现的

例子①:

redis >SET msg "hello world"
OK

Redis将在数据库中,创建一个新的键值对

  • 键值对的键是一个字符串对象,对象的底层实现是一个保存着字符串“msg”的SDS
  • 键值对的值也是一个字符串对象,对象的底层实现是一个保存着字符串"hello world"的SDS

例子②:

redis >RPUSH fruits "apple","banana","cherry"
(integer) 3

Redis将在数据库中,创建一个新的键值对

  • 键值对的键是一个字符串对象,对象的底层实现是一个保存着字符串“fruits”的SDS
  • 键值对的值也是一个列表对象,列表对象包含三个字符串对象,这三个字符串对象分别由三个SDS实现,第一个SDS保存着字符串"apple",第二个SDS保存着字符串"banana",第三个SDS保存着字符串"cherry"

SDS的定义
每一个sds.h/sdshdr结构表示一个SDS值:


struct sdshdr{
    //记录buf数组中已使用字节的数量
    //等于SDS所保存字符串的长度
    int len;
    
    //记录buf数组中未使用的字节的数量
    int free;
    
    //字节数组,用于保存字符串
    char buf[];
};

SDS示例

free属性:记录SDS中未使用的空间
len属性:记录SDS中已经使用的空间
buf属性:是一个char类型的数组,最后一个字节保存空字符’\0’

SDS特点
字符串和C中的字符串一样,都是以空字符结尾,并且空字符占用的1个字节空间不计算在len属性中,分配给空字符1个字节空间,以及自动添加空字符到字符串尾部都是SDS自动完成的

遵循空字符结尾的好处是可以使用一部分C字符串函数库中的函数,不需要再为SDS编写专门的一些函数。

SDS和C字符串的区别/也可以理解成已经有了C字符串,还要去设计SDS的原因

C语言中的字符串
长度为N+1的字符数组表示长度为N的字符串,最后一个元素为空字符’\0’

1.获取字符串长度的复杂度为O(1),提高了Redis的性能

C的复杂度为O(N)
因为要逐个元素进行遍历

因为SDS的属性len就记录了SDS的长度,直接获取len属性就可以知道字符串的长度,所以复杂度为O(1)

2.杜绝缓冲区溢出

为什么SDS可以避免上面这种情况?
当SDS的API对SDS进行修改的时候,API会先检查SDS的空间是否满足修改所需要的要求,比如内存等
如果检查发现不满足要求,API会自动将SDS的空间进行扩展至所需要的大小,然后再去执行实际的操作

3.减少修改字符串时带来的内存重分配次数
C语言
因为不记录字符串的长度,每次修改其长度的时候就和底层数组发生改变
,进行内存的重分配
如果增长字符串,先通过内存重分配扩展底层数组的空间大小
如果缩短字符串,先通过内存重分配释放字符串不需要的那部分内存

SDS
SDS通过未使用空间解除字符串长度和底层数组长度之间的关联
在SDS中,buf数组的长度不一定就是字符串数量加1,数值里面包含着未使用的字节,而这些字节的数量是通过SDS的free属性记录的

对于未使用空间,SDS采用了两种优化策略

空间预分配
用于字符串增长操作,当需要字符串增长时候,API对SDS进行修改并且对空间进行扩展,不仅会分配修改所需要的必要的空间,还会分配额外未使用的空间,也就是增长两个空间:要使用的空间和未使用的空间

惰性空间释放
用于字符串缩短操作,并不会立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性讲这些字节记录下来,并等待将来使用

总结

SDS API

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值