动态字符串用途:
1 保存库中字符串键值
2 用于缓冲区:AOF中的缓冲区
3 客户端状态中的输入缓冲区
在c语言中使用结构体实现动态字符串
struct sdshdr{
int len;
int free;
char buf[];
};
相比于C原生字符串优点:
1O(1)获得字符串长度
2 自动扩容,避免缓冲区溢出
C字符串需要人工申请空间,如果未申请导致溢出,会造成别的变量被意外修改。后果很严重。SDS在字符串增加、修改时会判断free+len能否满足变更后字符串的空间。不满足自动扩容。
内存重分配:
执行增长字符串操作,通过内存重分配扩展底层数组的空间大小。避免缓冲区溢出。
执行缩短字符串操作,通过内存重分配释放字符串不再使用的部分空间。避免内存泄露。
内存重分配,涉及到内存分配算法(满足当前空间需求,尽量减少内存碎片,确定分配哪块空间给当前内存更加合适),并有可能执行系统调用,耗时较高。Redis中需尽量避免内存重分配操作次数。
Redis通过free将底层数组与字符串实际长度隔离。
Redis 空间预分配 以及 惰性空间释放 两种优化策略:
1 空间预分配
用于优化字符串增长操作:修改且需要扩展空间时。为其分配额外的空间
1 修改后实际小于1MB 分配2*len(修改后的长度)+1的空间 1为空字节
2 修改后大于1MB 分配 len+1MB+1byte 的空间 其中free=1MB len为修改后的长度串所占空间大小
3 修改字符串时,如free足够择不进行扩展
2 惰性空间
当字符串缩短时,redis不会执行内存重分配回收空间的空间,而是将空间记录在free中便于之后使用。
在需要时,redis会释放SDS中free中的空间。
二进制安全:
C字符串认为到\0择字符串截止 如字符串中想存入\0择会出现问题
SDS使用len作为字符串截止的标准 不会存在二进制安全问题