因为redis使用C语言实现
- 定义
结构体
struct sdshdr{
//记录buf数组已经使用字节的长度
//等于SDS已经保存字符串的长度
int len;
//记录buf数组未使用的长度
int free;
//字节数组,用来保存字符串
}
buf是char类型的数组,最后一个字符为’\0’,不管是C语言字符串还是SDS字符串都以’\0’作为结束.并且分配一个字节,但是不记录在SDS的len内,遵循这个一空字符串结尾的习惯好处是可以重用C语言字符串的一些函数 - SDS与C语言字符串的区别,为什么Redis更适合SDS
(1). SDS字符串记录了字符串的len,在获取长度这里复杂的从O(n)降成O(1),这确保获取字符串长度的工作不会成为redis的瓶颈,哈哈,那么STRLEN 命令的复杂的为O(1)
(2). 杜绝缓冲区溢出,C语言字符串在进行拼接操作的时候需要提前分配足够的空间,否则产生缓存溢出,也就是空间不足了,SDS字符串修改之前会主动计算,不满足扩展空间
(3). C语言频繁的计算字符串需要的空间,频繁的内存重分配,SDS使用空间预分配和惰性空间释放两种优化策略
空间预分配是优化字符串空间增长的操作,对SDS扩展的时候,不仅分配必要的空间,还会分配格外未使用的空间,其中如果对SDS修改之后的字符串长度也就是len的属性大小小于1MB,那么程序还会分配空闲空间free一样的大小,其中free和len的大小相等,如果大于1MB,那么free的大小为1MB | 惰性空间释放是应用于字符串缩短操作,不是立即回收,而是留下来记录在free里边,等待后续的使用 |
(4). 二进制安全,C语言字符串必须符合某种编码(比如ascll),并且除了末位之外不能包含空格字符,所以C语言只能保存文本数据,而不能保存图片文件,原因是C语言保存的最后都是以这个’\0’ 结尾,碰到第一个就会被认为结束,所以造成数据的不完整,而SDS则可以保证二进制的数据完整性也就是数据安全,原因是SDS最后的字符才是’\0’,所以可以保存任意格式的二进制数据.
(5). 兼容C语言字符串的一部分函数,说白了就能用C语言函数(字符串的),SDS最后总是保存一个字节的’\0’
- 总结
对比项目 | C语言 | SDS字符串 |
---|---|---|
获取字符串长度的复杂度 | O(N) | O(1) |
API安全吗?会不会造成缓存溢出 | 不安全,可能造成缓存溢出 | 安全,不会出现缓存溢出 |
修改字符串长度N次,造成内存重分配的次数 | 必然n次 | 最多n次 |
文本保存 | 只能为文本数据 | 文本或者二进制格式 |
对于C语言库函数的使用<string.h> | 全部 | 部分 |