1、简单动态字符串SDS

1、简单动态字符串SDS全称simple dynamic string。
SDS是Redis自己构建的抽象类型,并将SDS用作Redis的默认字符串表示。
 
例如:set msg "hello world"
其中键msg是一个字符串对象,对象的底层实现是一个保存着字符串msg的SDS;
其中值为hello world是一个字符串对象,对象的底层实现是一个保存着字符串"hello world"的SDS。
 
结构为:
struct sdshdr{
//记录buf数组中已经使用字符的长度 等于 SDS保存字符串的长度
int len;
//记录buf数组中未使用字节长度
int free;
//字符数组,用于保存字符串
char buf[];
}
 
SDS总是以'\0'空字符结尾,并且'\0'空字符不记录在len字段中,例如:
set name "Redis"
这个设置name="Redis"的键值对中,"Redis"的SDS格式如下:
struct sdshdr{
5;
0;
['R','e','d','i','s','\0'];
}
2、SDS与C字符串区别
C字符串:
缺点:
获取字符串长度的复杂度为O(N)
API不安全,可能会造成缓存区溢出( 对于一个字符串A后面拼接字符串B时,需要考虑A字符串的容量问题)
修改字符串长度N次必然需要执行N次内存重分配( 即无论是缩小还是扩大C字符串的大小都需要进行内存分配)
只能保存文本数据( 即C字符串是以'\0'结尾的,如果想保存'\0'这个特殊字符,则会导致数组提前被截取了)
优点:
可以使用所有<String.h>库中的函数
SDS:
优点:
获取字符串长度的复杂度为O(1)
API是安全的,不会造成缓存溢出问题
修改字符串长度N次最多需要执行N次内存重新分配( 由于SDS结构中有free字段的存在,因此缩小时,会把没有的char算到free中(惰性空间释放),而放大(空间预分配)时如果len长度<1M,则扩大后的len=原有len*2,如果len长度>=1M,则扩大后的len=原有len+1M)
可以保存文本或者二进制数据( 因为SDS获取字符串时是根据len长度算的,而不是根据'\0'结尾之前的字符串算)
可以使用一部分<String.h>库中函数(不需要重新实现)
 
总结:
为什么Redis速度快?
一部分原因:
Redis自建的SDS结构,包括获取字符串长度的复杂度为O(1)、修改字符串长度N次最多需要执行N次内存重新分配、可以使用一部分<String.h>库中函数(不需要重新实现)。

猜你喜欢

转载自www.cnblogs.com/use-D/p/9704273.html