概念
redis在c的基础上编写,但是redis的许多数据结构是不同于c的数据结构。
redis的字符串表示是利用自己构建的SDS(简单动态字符串)作为默认字符串表示的。
而c默认的字符串表示,被redis用来作为字面量的表示方法,字面量,就是字符串是固定的,不会改变的。
SDS的用处:
- 保存动态字符串值
- 缓冲区:AOF缓冲区、客户端状态的输入缓冲区
sds定义:
struct sdshdr {
int len; // 已使用的buf[]长度
int free; // 未使用的buf[]长度
char buf[]; // 保存char字节, buf[]数组默认结尾为‘\0’,且不被记入len。
}
SDS与c字符串的区别有:
- 获取字符串长度复杂度:
- c需要遍历字节数组以获得字符串长度,sds只需要获取len值即可。
- 杜绝缓冲区溢出:
如上图所示:在内存中,紧挨着两个c字符串,当执行strcat(s1,'Cluster')
时,默认s1的长度足够,那么‘Cluster’就会覆盖后面s2的内容,即“内存溢出”。
Sds的api进行修改时,会首先检查sds的内存空间是否足够,如果不够会触发自动扩容。
sds空间策略:
空间预分配
概念:当sds的api对sds进行扩容操作时,不仅会分配所需的空间,还会为sds分配多余的空间
内容:
- 如果sds被修改后,len的长度小于1MB,那就会为sds多分配len长度的空间,此时len=free
举例说明:修改'hello'为'hello,redis', 修改后长度为11字节,那么就会在修改后,继续为sds分配11字节的空间,此时len = free。sds实际长度为11+11+1=23字节。 - 如果sds被修改后,长度大于1MB,那么就会在修改后,继续为sds分配1MB的free空间。
惰性空间释放
概念:sds删除部分字符串后,不会讲空出来的空间立即删除。
内容:
- 如图,部分空间即使存储的内容被删除也不会被立即释放,会作为free空间保留在sds中,在之后的增长操作中使用。为避免空间浪费,有api真正释放free空间。
sds二进制安全
二进制安全
概念:sds不是以'\0'作为字符串结尾,所以不用担心某些以'\0'分隔的数据格式。
内容:
- ‘Redis Cluster’, 如果使用二进制保存,c的字符串函数只会识别Redis,而忽略后面的'Cluster', 这就导致c的字符串只能用来保存文本,而图片、视频等二进制数据无法保存。而sds的二进制安全,表示sds的buf[]能直接处理二进制数据,这也是buf[]是字节数组的原因。因为sds使用len属性而不是空字符串判断结尾。
兼容C部分函数
因为SDS字符串以'\0'结尾,所以可以兼容c的部分字符串函数。
标签:sds,redis,len,free,字符串,长度,动态 From: https://www.cnblogs.com/wz-NO1/p/17228052.html