Redis 只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(简单动态字符串)作为字符串表示。

114 阅读2分钟

Sds比c字符串的优点

1) 常数复杂度获取字符串长度。

C字符串不记录自身长度信息,获取c字符串长度的操作,是采用遍历操作整个字符串,对每个字符进行计数,直到结尾的空字符为止;SDS在len属性中记录了SDS本身的长度,读取len属性即可获得字符的长度

2) 杜绝缓冲区溢出

因为c字符串不记录自身长度,所以用户在执行字符串拼接操作(srccat),如果目标字符串内存空间不足,而紧邻的空间又有内容保存,那么紧邻的空间的内容将被占用,原来保存的内容被覆盖,产生缓冲区溢出。SDS空间分配策略完全杜绝了发生缓冲区溢出的可能性:当需要对sds进行修改是,首先先检查sds空间是否满足修改所需的要求,如果空间不足,先自动对SDS进行空间扩展,然后再执行修改操作。

3) 减少修改字符串长度时所需的内存重分配次数

因为C字符串不记录自身长度,C字符串数据的最后一位用于保存空字符作为终结,而对C字符串进行拼接或者删减,都要对内存空间进行重分配扩展数组空间或释放空间,如果不进行空间重分配,前者会造成缓冲区溢出,后者会产生内存泄漏。

SDS数组长度不一定是字符串数量加一,SDS实现了空间预分配和惰性空间释放两种优化策略进行空间的管理。

a) 空间预分配,当SDS进行空间扩展时,不仅会分配修改所需空间,还会分配额外的未使用空间(如果修改之后的空间小于1MB,修改后的实际长度为修改后的长度*2+1,额外的1字节用于保存空字符串;如果修改之后的长度大于等于1MB,会在再多分配1MB的未使用空间,实际长度修改后的长度+1MB+1byte)

b) 惰性空间释放,SDS字符串进行缩短操作,程序并不立即使用空间重分配来缩短多出来的字节,而是用free属性记录下来,以备下次使用

4) 二进制安全

C字符串的字符必须符合某种编码格式,并且字符串里不能包含空字符串,这就决定了C字符串只能保存文本数据,而不能保存图片、音频、视频和压缩文件这样的二进制数据

5) 兼容部分c字符串函数

Redis就不用自己专门写一个函数对比SDS和C字符串值