1、Redis的SDS
redis中使用的默认字符串与c语言默认使用的不太一样,C语言使用空字符结尾,Redis自己封装了一种简单的动态字符串(simple dynamic string,SDS)。在源代码sds.h中可以找到SDS的定义(本文参考3.0.0版,3.2.0之后会有变化),如下所示:
1 //sds.h 2 struct sdshdr { 3 unsigned int len; 4 unsigned int free; 5 char buf[]; 6 };
可以用下图来说明一下:
len值为5:表示该SDS有5个字符,
free值为0:表示该SDS没有分配任何多余的空间
buf是一个char类型的数组。前面存储len个有效字符。
SDS也遵循字符串以'\0‘结束的习惯,最后的'\0’不计算在len内,完全由redis函数自己添加。因此,可以直接使用c的函数来处理该buf。
free值不为0时,'\0'的位置如下图所示:
2、SDS与C字符对比的优势
- len记录了字符的长度,因此可以以常数复杂度获取字符串长度,而普通的字符串需要经过遍历之后才能获取其长度。
- free记录了剩余空间,可以避免缓冲区溢出。C语言的字符串是可以直接追加的,默认假设有多余空间可以使用,一旦假设不成立,则会出现溢出。
- 通过预配内存,以及使用函数及时调整len和free,在free空间足够时,可以避免重新分配内存(申请内存是比较耗时的操作)。在减少字符串长度时也不必立即释放内存。
- 二进制安全:C字符串遇到空字符则认为已经结束,无法表示一些中间含有空字符的二进制数据,redis使用len记录长度,而不是空字符判断是否结束。redis不仅仅是用来保存字符串用的,可能用来存储图片,视频,压缩文件等二进制数据。