小白的Redis学习(一)-SDS简单动态字符串
本文为读《Redis设计与实现》的记录。该书以Redis2.9讲解Redis相关内容。请注意版本差异。
Redis使用C语言实现,他对C语言中的char类型数据进行封装,构建了一种简单动态字符串(以下简称SDS),该字符串的结构如下
struct sdshdr{ //记录buf数组中已使用字节的数量
//获取字符串的长度时,就是直接返回的这个字段的值
int len; //记录buf数组中未使用字节的数量 int free; //字节数组,用于保存字符串 char buf[]; }
SDS遵循C语言中,字符串以空字符结尾的惯例。该空字符会在buf[]中占一位,但是不会统计到字符串长度 len中,这个空字符对于编程者来说,是透明的。
如Redis在SDS中存储的方式可能为
len = 5;
free = 0;
buf = {'R','e','d','i','s','\0'}
free是指buf中的预留长度。他的值遵循以下三种规则
1) buf数组删除掉一部分时,buf的长度不会立即改变,删除的长度会先累加进free的值中。
2) buf数组新增一部分时,若free的值大于新增的长度,则free减去新增的长度,若free小于新增的长度,则对buf进行扩容,free = len + 新增的长度 ,buf = 2 * free + 1,加的1是'\0' 空字符的值
3) free的最大值不超过1M
总结:SDS的扩容遵循了类似于hashMap扩容的*2规则,通过增加空间复杂度,减少了时间复杂度,空间最大的花费忍耐度是1M。
SDS与C语言中的普通字符串的一个大的区别是:SDS允许字符串的中间出现空字符。SDS字符串的结束标识是根据len的大小来进行判断的,末尾额外的增加一个空字符,只是为了使用一部分C语言中提供的API。这样,SDS就可以储存一些图像、音频、视频、压缩文件这样的二进制数据。而C语言中的一般字符串遇到空字符就判断字符串结束。无法存储这些二进制文件。
总的来说,SDS的优点如下:
1) 常数复杂度的获取字符串长度
2) 杜绝缓冲区溢出
3) 减少修改字符串时所需的内存分配次数
4) 二进制存储安全
5) 兼容部分C字符串函数