Redis中的简单动态字符串
- Redis使用了一种名叫SDS(简单动态字符串)的抽象类型来代替C语言传统的字符串表示,主要用于存储键值对,用作缓冲区等
SDS的定义
- sdshdr表示SDS的头部指针
- free表示buf数组中未使用的字节数量
- len表示buf数组中已使用的字节数量(字符串长度),其在字符串最后存储占据一个字节的'\0',目的是为了兼容C语言的一些函数
SDS内存的分配与释放
空间预分配机制
// 伪代码
if(len < 1MB) {
free = len;
}
else {
free = 1MB;
}
buf.length = free + len + 1byte;
惰性空间释放
SDS与C语言字符串的区别
获取字符串长度 |
复杂度为O(1) |
复杂度为O(N) |
API |
安全接口,不会造成缓冲区溢出 |
不安全,可能会造成缓冲区溢出 |
修改字符串长度 |
N次最多需要执行N次内存重分配 |
N次必然执行N次内存重分配 |
文本数据 |
可以保本文本或者二进制数据 |
只能保存文本数据 |
库函数 |
可以使用一部分 |
可以使用全部 |
SDS的主要操作API
sdsnew |
创建一个包含给定C字符串的SDS |
O(N),N为给定字符串的长度 |
sdsempty |
创建一个不包含任何内容的空SDS |
O(1) |
sdsfree |
释放给定的SDS |
O(N),N为被释放的SDS的长度 |
sdslen |
返回SDS的已使用空间字节数 |
O(1) |
sdsavail |
返回SDS的未使用空间字节数 |
O(1) |
sdsdup |
创建一个给定的SDS的副本 |
O(N),N为给定SDS的长度 |
sdsclear |
清空SDS保存的字符串内容 |
O(1) |
sdscat |
将给定的C字符串拼接到SDS字符串的末尾 |
O(N),N为被拼接的C字符串的长度 |
sdscatsds |
将给定的SDS字符串拼接到另一个SDS字符串的末尾 |
O(N),N为被拼接的SDS的长度 |
sdscpy |
将给定的C字符串复制到SDS里面,覆盖SDS原有的字符串 |
O(N),N为被复制C字符串的长度 |
sdsgrowzero |
用空字符将SDS扩展至给定长度 |
O(N),N为扩展新增的字节数 |
sdsrange |
保留SDS给定区间内的数据,不在区间内的数据会被覆盖或清除 |
O(N),N为被保留数据的字节数 |
sdstrim |
接受一个SDS和一个C字符串作为参数,从SDS中移除所有在C字符串中出现过的字符 |
O(N^(2)),N为给定C字符串的长度 |
sdscmp |
对比两个SDS字符串是否相同 |
O(N),N为两个SDS中较短的那个SDS的长度 |