SDS-简单动态字符串

定义

SDS(simple dynamic string),Redis底层使用它作为默认字符串,当我们想redis存储一个键值对时,redis会在数据库创建一个新的键值对,而这个键值对的键和值都是以SDS来存储的。

每个sds.h/sdshdr结构标示一个SDS值。

struct sdshdr{
  //记录buf数组中已使用字节的数量,等于SDS所保存字符串的长度
  int len;
  //记录buf数组中未使用字节的数量
  int free;
  //字节数组,用于保存字符串
  char buf[];
};

SDS-简单动态字符串

 free代表这个SDS分配的未使用空间;len代表这个SDS保存字符串的长度;buf表示存储的字符串的值,是一个char类型的数组,末尾的' '代表一个空字符。

SDS的优势(和C字符串对比):

1、常数复杂度获取字符串长度

C字符串自身不记录自己的长度信息,所以要获取一个c字符串的长度就必须遍历整个字符串,对遇到的每个字符进行计数,直到遇到空字符位置,此操作的复杂度为O(n)。而SDS本身通过len记录了自身的长度,可以直接获取,所以复杂度仅为O(1)。

2、杜绝缓冲区溢出

当SDS改变时,SDS的API会首先检查SDS的空间是否满足修改所需的要求,如果不满足的话,API会自动将SDS的空间扩展至修改所需要的大小,然后才进行实际的修改操作。

3、减少修改字符串带来的内存分配次数

SDS通过空间预分配和惰性空间释放来减少修改字符串带来的内存分配次数。空间预分配用于优化SDS的字符串增长操作:当SDS的API对一个SDS进行修改,并且需要对SDS的空间进行扩展的时候,程序不仅会为SDS分配修改所必须的空间,还会为SDS分配额外的未使用空间。当修改后的长度小于1MB,那么程序分配和len属性同样大小的未使用空间;如果大于1MB,那么程序会分配1MB的未使用空间。惰性空间释放用于优化SDS的字符串缩短的操作:当SDS的API需要缩短SDS保存的字符串时,程序不会立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性记录起来,并等待将来使用。

4、二进制安全

SDS的buf属性不是保存的字符,而是一系列二进制数据,因此可以用来保存任何特殊数据格式。在读的时候使用的len属性值而不是空字符串来(C是使用空字符串)判断字符串是否结束。