redis字符串实现
redis采用c语言里面的SDS(simple dynamic string),C语言中, 结构如下
struct sdshdr {
//已使用长度
ing len;
//剩余长度
int free;
//字符串内容
char buf[];
}
使用该结构的好处
- c语言字符串没有长度,如果获取长度需要遍历char数组,耗时过大
- SDS结构获取跟设置长度的时间复杂度都是O(1)
- 杜绝缓冲区长度溢出,C语言字符串不记录长度,所以可能会导致字符串长度溢出。SDS在api层拥有空间分配策略,从而进行长度的校验空间大小以及自动扩展空间
- 使用C语言字符串每次新增跟删除字符串都需要进行内存空间的重新分配,耗时。如果不分配就会出现内存泄漏或者溢出。使用SDS通过标记未使用的 + (空间预分配、惰性空间释放)策略。通过空间预分配策略来减少由于修改字符串带来的内存重新分配次数。
内存分配策略简介
空间预分配(发现空间不够,提前分配下次需要的空间)
在进行字符串长度变更的时候,如果内存不够用,那么进行重新分配内存空间的时候不仅仅会分配需要的空间,也会分配额外的free的空间,以便下次字符串变更的时候,不需要进内存空间进行重新分配
惰性空间释放(不用的空间不释放,下次用)
字符串进行缩短的时候,不会进行内存重新分配,将剩余的空间用free字段记录空闲空闲长度,避免下次进行字符串操作的时候需要重新分配内存。当然SDS也提供了api,当我们真正需要释放SDS内存的时候进行调用api来操作。
总结
| C字符串 | SDS |
|---|---|
| 获取字符串长度时间复杂度O(N) | 获取字符串长度时间复杂度O(1) |
| API不安全,可能会造成内存溢出跟泄漏,需要手动处理 | API是安全的,通过length字段来判断内存空间是否够用 |
| 每次修改字符串都要进行内存重新分配,耗时。 | 修改字符串未必要进行内存分配,因为有free空间的存在 |