Redis构建了一种名为简单动态字符串(SDS)的抽象类型,并将SDS用作Redis的默认字符串表示
SDS的特点是:可动态扩展内存、二进制安全和与传统的C语言字符串类型兼容。然后从源码中
进行分析(主要是在sds.c和sds.h两个文件中)
在Redis源码sds.h文件中我们可以看到数据结构定义,
typedef char *sds;
Redis采用一整段连续内存进行存储sds结构,并且可以和传统的c语言字符串类型兼容。
SDS字符串有5种类型,第一种:
struct attribute ((packed)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};
这一种是从不用来使用字符串,只是用来访问标志字节。
第二种:
struct attribute —((packed)) sdshdr8 {
uint8_t len; /* used */
uint8_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
在这个里面,len:表示SDS所保存字符串的长度,不包含空终止字符
alloc:表示字符串的最大容量,不包含Header和最后的空终止字符
flags:第三位表示header的类型,目前主要有七种类型,高五位未使用,这里未使用的部分可
以对以后的需要进行扩展,后面如果还有其他的类型完全可以不变该结构的情况下进行扩展。
剩下的三种和第二种类似只是把上面的数字8换成了16,32,64。区别是为了表示不同的大小
使用SDS而不是C字符串,原因:
1.C字符串获取本身的长度复杂度是O(N),SDS获取一个SDS长度的复杂度仅为O(1),使得获
取字符串长度的动作不会成Redis的性能瓶颈
2.杜绝缓冲区溢出。SDS API需要对SDS进行修改时,会先检查SDS空间是否满足空间的要求,不
满足,API会自动将SDS的空间扩展至执行修改所需大小。然后才执行修改操作。
3.减少修改字符串时带来的内存重分配次数。
4.二进制安全,C字符串必须符合某种编码,除了字符串的末尾外,不能包含空字符,否则会被
误认为是字符串的结尾,导致最终读取的字符串是不完整的。这些限制导致了字符串不能用于
存放图片、音频、视频等二进制数据,只能存放文本数据。但是在Redis中,不是靠空字符来判
断字符串的结束的,而是通过len这个属性。那么,即便是中间出现了空字符对于SDS来说,读取
该字符仍然是可以的。
5.兼容部分C字符串。
参考资料:https://blog.csdn.net/wangyang1354/article/details/52727115
《redis设计与实现第二版》