1. Redis 没有直接使用c语言的字符串(以空字符结尾的字符数组),而是自己构建了一 种名为简单动态字符串(Simple Dynamic String , SDS),并将SDS做为 redis的默认字符串。
2.在redis数据库里面,包含字符串的键值对,底层都是由SDS实现的。
3.举例说明:
(1)在redis客户端执行:set msg "HelloWorld" ,那么,redis在数据库中将会创建一个新的键值对。键值对的键对象的底层实现,是由一个保存着字符串msg的SDS实现的。
键值对的值是一个保存着HelloWorld的SDS.
(2) 执行:set fruit "apple" "banana" "orange" ,那么,键值对的键是一个保存着fruit字符串的SDS。
键值对的值是一个列表对象,列表对象,包含三个字符串对象,三个字符串对象底层分别由三个SDS实现。
4.SDS的实义
如图:
(1)free 属性为0,表示这个SDS没有分配任何未使用空间。
(2)len 属性为5,表示这个SDS保存着一个5字节长的字符串
(3)buf 属性是一个char类型的数组,数组的前五个字节分别保存了,'R' 'e' 'd' 'i' 's' ,而最后一个字节保存了空字符 '\0' (以空字符结尾),最后一个空字节不计算在len属性里面。
下图是另一个例子,free是5,表示SDS为buf分配了5个未使用的字节空间。
5.SDS的空间优化策略
(1) 空间预分配
a. 对SDS进行修改后,如果SDS的长度小于1M,那么程序将分配和SDS的len属性相同大小的未使用空间,这时SDS的len属性值将和free属性值相同。
如果修改后SDS的len变成13字节,那么程序将会给SDS再分配13字节的未使用空间,SDS的buf数组的长度为13+13+1(空字符结尾)=27字节。
b. 如果对SDS修改之后,SDS的长度大于1M,那么程序将分配1M的未使用空间给SDS。
如果修改后SDS的len变成3M,那么buf的长度是 3M+3M+1byte
通过这种预分配策略,SDS将连续增长N次字符串的内存重分配次数,从必定N,降低为最多N。
(2)惰性空间释放策略
当需要缩短SDS保存的字符串时,程序并不使用内存重分配,来回收缩短之后多出来的字节。而是使用free属性将这些字节记录下来,并等待将来使用。
举例说明:
如果SDS存的是 abcdefghij 现在删除hij,会将sds修改成如下图,free属性变为3,这样如果将来要对SDS进行增长操作的话,就不用重新分配内存空间。
另:SDS提供了相应的api用于释放内存空间,所以不用担心内存浪费。(有时间把图补上)