1. 简介
Redis没有使用C中默认的字符串(字符数组),而是自己构建了一个简单动态字符串(SDS)的抽象类型,并且作为默认的字符串。
- Redis中会使用C中的字符串作为字符常量,用在无需修改的地方,如日志;
- 当字符串会被修改时,就是使用SDS;
- 此外,SDS还会被用作缓冲区。
2. 定义
sds.h/sdshdr
结构体表示一个SDS值:
struct sdshdr {
unsigned int len;
unsigned int free;
char buf[];
};
相比普通的C字符串,SDS的优点在于:
- 能够通过len字段方便的知道字符串长度;
- 通过free字段能方便知道缓存区剩余空间;
- 同样字符串buf以' '结尾,能够与print等C中函数接口通用;
- 杜绝缓冲区溢出(SDS会先进行检查,空间不够会进行扩展)。
- 二进制安全。
在使用SDS API的情况下,不要手动修改len和free字段,它们的维护是API内部自动进行的。
3. 内存优化策略
3.1 空间预分配
在使用SDS API进行字符串修改需要扩容时,不仅会分配修改所必须的空间,而且还会分配额外的未使用空间。总体策略:
- 如果修改后的SDS长度(len字段)小于1MB,那么程序会分配同len相同的未使用空间,即free=len,实际长度是free+len+1=2len+1;
- 如果修改后的SDS长度(len字段)大于1MB,那么程序会分配1MB的未使用空间。
通过空间预分配,可以减少内存分配次数。
3.2 惰性空间释放
释放策略是:弹药使用API缩短SDS字符串时,程序并不会回收多出来的字节,而是使用free字段记录下来,以等待将来被使用。
通过惰性空间释放,可以减少内存回收的次数,未回收的内存可以继续用于字符串的存储。
如果要回收内存,SDS提供了相应的API。
4. 特点
4.1 二进制安全
虽然SDS的buf保存了C的