redis 是用C语言写的,但是对于redis 的字符串,却不是C语言中的字符串,它自己构建了一种名为简单动态字符串的抽象对象(simple dynamic string, SDS)
SDS 属性
- len 保存了SDS字符串的长度
- buf[] 数组用来保存字符串的每个元素
- alloc 分别unit8, unit16, unit32, unit64 表示整个SDS,除过头部与末尾的\0, 剩余的字节数
- flags 始终为一字节,以低三位标示着头部的类型,高5位未使用
为什么使用SDS
- 由于len属性的存在,获取字符串长度时间复杂度为O(1)
- 杜绝缓冲区溢出,可以根据len属性检查内存空间是否满足需求,不满足会进行空间扩展
- 减少字符串的内存重新分配次数
对于SDS,由于len属性和alloc属性的存在,对于修改字符串SDS实现了空间预分配和惰性空间释放两种策略:
1、空间预分配:小于1M,每次扩展1倍,大于1M,每次额外多分配1M
2、惰性空间释放:对于字符串进行缩短操作时,不立即使用回收多余内存,而是使用alloc 属性记录,待后续使用 - 二进制安全
因为C字符串以空字符作为字符串结束的表示,而对于一些二进制的数据(如图片等),内容可能包括空字符串,因此C字符串无法正确存取; - 兼容部分C字符串函数 在数据结尾添加了\0