参考:http://redisbook.com/preview/sds/different_between_sds_and_c_string.html
Redis 只会使用 C 字符串作为字面量, 在大多数情况下, Redis 使用 SDS (Simple Dynamic String,简单动态字符串)作为字符串表示。
比起 C 字符串, SDS 具有以下优点:
- 常数复杂度获取字符串长度。
- 杜绝缓冲区溢出。
- 减少修改字符串长度时所需的内存重分配次数。
- 二进制安全。
- 兼容部分 C 字符串函数。
C 字符串和 SDS 之间的区别
C 字符串 | SDS |
---|---|
获取字符串长度的复杂度为 O(N) 。 | 获取字符串长度的复杂度为 O(1) 。 |
API 是不安全的,可能会造成缓冲区溢出。 | API 是安全的,不会造成缓冲区溢出。 |
修改字符串长度 N 次必然需要执行 N 次内存重分配。 |
修改字符串长度 N 次最多需要执行 N 次内存重分配。 |
只能保存文本数据。 | 可以保存文本或者二进制数据。 |
可以使用所有 <string.h> 库中的函数。 |
可以使用一部分 <string.h> 库中的函数。 |
1、为啥可以使用部分string.h里面的函数?
遵循 C 字符串以空字符结尾的惯例, SDS 可以在有需要时重用 <string.h>
函数库, 从而避免了不必要的代码重复。
2、SDS获取字符串长度为啥O(1)?
通过len字段存储buf的长度,更新sds的时候自动更新记录,获取长度直接读取len的大小
3、为什么API 是安全的,不会造成缓冲区溢出?
比如strcat拼接字符串的时候,通过SDS->free长度记录剩余空间,如果不够会分配空间,再写入
4、修改字符串长度 N
次最多需要执行 N
次内存重分配。空间分配策略是什么样的?
空间预分配:长度小于1m,比如13k,直接预分配free=13k的空间,时间空间=len+buf+1bytes;长度大于1m,预分配free=1m,实际空间=len+1m+1bytes;
惰性空间释放:减少字符串后,不会立马释放空间,记录到free字段,并等待将来使用。等定时器定时检测和释放空间?
5、为什么是二进制安全?
以len的长度读取数据,判断结尾,不是空字符串\0作为结尾,所以可以存储二进制数据