Redis数据结构——SDS简单动态字符串

1,C语言中定义的字符串是以空字符结尾的字符数组,而Redis中自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型。
2,sds的结构如下:

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

//记录buf数组中未使用字节的数量
int free;

//字节数组,用于保存字符串
char buf[];
}

3,SDS与C字符串的区别
1)常数复杂度获取字符串长度,程序计算C字符串的长度的方法是遍历整个字符串,直到遇到空字符为止。这个操作的复杂度为O(N),而SDS在len属性中记录了SDS的长度,因此O(1)复杂度就可以获取。其实程序重复执行strlen函数也不会影响系统性能。
2)杜绝缓冲区溢出
因为C字符串不记录自身的长度,使用strcat函数的时候,不会先检测内存够不够,这就有可能造成缓冲区溢出。
SDS的空间分配策略杜绝了发生缓冲区溢出的可能性。当SDS的API需要对SDS进行修改时,API会先检查SDS的空间是否满足修改所需的要求,如果不满足要求的话,API会自动将SDS的空间扩展至执行修改所需的大小。
3)SDS可以减少修改字符串时带来的内存重分配次数
因为C字符串底层实现总是一个N+1个字符长度的数组,因为C字符串的长度和底层数组的长度之间存在着这种关联性,所以每次增长或缩短C字符串,程序总会对保存C字符串的数组进行一次内存重分配操作:
如果程序执行的是增长字符串的操作,比如拼接操作,那么在执行这个操作之前,程序需要先通过内存重分配来扩展底层数组空间大小——如果忘了这一步就会产生缓冲区溢出;
如果执行的是缩短字符串的操作,比如截断操作,那么在执行这个操作之后,程序需要通过内存重分配来释放字符串不再使用的那部分空间——如果忘了这一步就会产生内存泄漏。
SDS的额外分配的未使用空间数量由以下公式决定:
如果对SDS进行修改后,SDS的长度小于1MB,那么程序分配和len属性同样大小的未使用空间。如果修改后SDS的长度大于1MB,程序会分配1MB的未使用空间。
SDS的惰性空间释放并不是真正的释放空间,而是将要释放的空间加到free里面。
4)SDS是二进制安全的,SDS的API都会以处理二进制的方式来处理SDS存放在buf数组里的数据,数据在写入时什么样,它被读出时就是什么样。**Redis不是用buf这个数组来保存字符,而是用它来保存一系列二进制数据。**使用SDS来保存特殊数据格式就没有任何问题,因为SDS使用len属性的值而不是空字符来判断字符串是否结束。
5)SDS可以使用一部分C字符串函数

猜你喜欢

转载自blog.csdn.net/xiaoan08133192/article/details/115076327