简单字符串(Simple Dynamic String,SDS)
SDS是Redis自己构建的一种抽象类型,并将SDS用作Redis的默认字符串表示
sds.h/sdshdr
struct sdshdr {
// 记录buf数组中字节长度,即SDS所报寸字符串的长度
int len;
// 记录buf书中未使用的字节数量
int free;
// 字节数组,用于保存字符串
char buf[];
};
举个栗子
redis> SET k1 "v1"
那么redis将在数据库中创建一个新的键值对,其中
- 键(k1),是一个SDS,len = 2, free = 0,buf[] = |’k’|’1’|’\0’|
- 值(k1),是一个SDS,len = 2, free = 0,buf[] = |’v’|’1’|’\0’|
空间预分配
当对 SDS 进行增长操作时,程序不仅会为 SDS 分配修改所需要的内存空间,还会为 SDS 分配额外的未使用的内存空间
分配策略
- 修改 SDS 后属性 len < 1MB,程序分配和 len 一样大小的未使用的内存空间,例如:修改后 SDS 的 len = 20 byte,那么程序也分配 20 byte 作为未使用的空间(free = 20 byte),此时 SDS 的 buf 数组的实际长度为 20 + 20 + 1 = 41 byte(1 byte 保存空字符串)
- 修改 SDS 后属性 len > 1MB,程序分配 1MB 未使用的内存空间,例如:修改后 SDS 的 len = 20 MB,那么程序分配 1MB 大小的未使用空间,此时 SDS 的 buf 数组实际长度为 20MB + 1MB + 1byte。
惰性释放空间
减少 SDS 长度后,不会释放空余内存空间,而是将其做为未使用空间保留在SDS里面,并记录在 free 属性中,如果将来需要扩展 SDS ,有可能就不需要重新进行内存重新分配操作。
重点
- 获取字符串长度的复杂度从O(N)降低到O(1)
- 没有缓冲区溢出
- 减少修改字符串长度时所需的内存重新分配次数
- 二进制安全,使用len属性标记结束点
- 兼容部分C字符串函数