一 SDS的定义
- Redis没有使用C语言传统的字符串表示,他自己构建了一个简单动态字符串的抽象类型,他就是SDS,redis里面C字符串只会用来无需对字符串进行修改的地方,比如打印日志
数据结构
struct sdshdr {
// 记录buf数组中已使用字节的数量 // 等于SDS所保存字符串的长度 int len; // 记录buf数组中未使用字节的数量 int free; // 字节数组,用于保存字符串 char buf[]
}
sds遵循空字符串结尾,因为这样可以直接重用C字符串里面的一些函数比如打印 printf("%s",s->buf)
二 SDS与C字符串的区别
- 常数复杂度获取字符串长度
记录自身的长度信息,所以每次获取长度都要遍历,而SDS通过len可以直接得到长度信息,节省性能
- 杜绝缓存区溢出
C语言的字符串不记录自身的长度信息,所以在执行
strcat
向一个字符串结尾追加另一个字符串时,如果不先扩容,就会把前面的字符串覆盖掉,造成缓存区溢出 减少修改字符串时带来的内存重分配次数
C语言的字符串不记录自身的长度信息,增加字符串就要扩容计算,就要重新分配,而SDS通过空间预分配,和惰性空间释放来减少内存重分配
空间预分配
如果占用空间小于1M,那么就分配和len同样的长度,也就是free空间
- 惰性空间释放
当字符串被删除,free空间并不跟着删除,这样下次增加的时候,就可以直接用free的空间
- 二进制安全
C字符串必须符合某种编码,但是有些编码对字符串的判断不一样,比如 redis look,中间有一个空格,对与某个编码可能就是要换行,导致问题,但是SDS判断字符串结束是通过len属性,所以不会有问题。