Nivelle 开拓视野冲破艰险看见世界 身临其境贴近彼此感受生活

redis深入学习之动态字符串

2017-07-24

简单动态字符串

当redis需要的不仅仅是一个字符串字面量,而是一个可以被修改的字符串值时,Redis就会使用SDS来表示字符串值,在Redis数据库里面,包含字符串值的键值对在底层都是由SDS实现的.(SDS:简单动态字符串)

例子:

redis> Set msg “hello world”

ok

其中:

  • 键值对的键是一个字符串对象,对象的底层是一个保存着字符串”msg”的SDS

  • 键值对的值也是一个字符串对象,对象的底层实现是一个保存着字符串”hello world”的SDS

redis> RPUSH fruits “apple” “banana” “cherry”

其中:

  • 键值对的键是一个字符串对象,对象的底层实现是一个保存了字符串”fruits”的SDS

  • 键值对的值是一个列表对象,列表对象包含了三个字符串对象,这三个字符串对象分别由三个SDS实现:分别是保存着”apple”,”banana”,”cherry”的三个SDS字符串

SDS定义

每个sds.h/sdshdr结构表示一个SDS值:


struct sdshdr{
  //记录buf数组中已经使用的字节的数量
  //等于SDS所保存字符串的长度
  int len;

  //记录buf数组中未使用的字节的数量
  int free;

  //字节数组,用于保存字符串
  char buf[];
}



与C字符串的区别

常数复杂度的字符串长度获取

杜绝缓冲区溢出

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

二进制安全

1.空间预分配

当SDS的API对一个SDS进行修改,并且需要读SDS进行空间拓展的时候,程序不仅会为SDS分配修改所必须的空间,还会为SDS分配额外的未使用空间.

  • 如果对SDS进行修改之后,SDS的长度(也即len属性的值)将小于1MB,那么程序分配和len属性同样大小的未使用空间,这时SDS len属性的值将和free属性的值相同.例如:如果进行修改之后,SDS的len将变成13字节,那么程序也会分配13字节的未使用空间,SDS的buf数组的实际长度将变成13 + 13 +1=27字节(额外的一字节用于保存空字符)

  • 如果对SDS进行修改之后,SDS的长度将大于等于1MB,那么程序会分配1MB的未使用空间.例如:如果进行修改之后,SDS的len的len将变成30MB,那么程序就会分配1MB的未使用空间,SDS的buf数组的实际长度将为30MB+1MB+1byte.

  1. 惰性空间释放

惰性空间释放用于优化SDS的字符串缩短操作:当SDS的API需要缩短SDS保存的字符串时,程序并不立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性将这些字节的数量记录起来,并等待将来使用.

redis设计与实现作者:黄健红


评论