SDS
- 什么是SDS
- SDS结构
- len的作用
- free的作用
- buf的作用
- 简单示例
- SDS机制
- 重新分配内存
- 分配内存机制
- 小于1MB情况
- 大于1MB情况
- 为什么这样分配
- 惰性释放内存
什么是SDS
SDS:全名 simple dynamic string,意为简单动态字符串,作为redis里的一种数据结构,它有着普通C字符所不具备的一些特点.
SDS结构
struct sdshdr {int len;int free;char buf[];
}
len 意指SDS所保存字符的长度
free 则指buf数组中未使用字节的数量
buf 字节数组,用于保存字符串
从结构设计上,我们可以对 SDS的设计的优点可窥一二
len的作用
首先从len开始,为什么SDS会记录一个len值,熟悉遍历大法的我们知道,要想知道一个字符串的长度,最原始的办法是从首位数到末位,假如我们有一个长度为n的字符串,在未记录其长度时,我们要想知道其len值,需要话费的时间会是O(N),如果我们是使用的SDS记录的字符串,则花费时间使用STRLEN为O(1),花费的时间越少,意味着性能越高.
free的作用
free,意指buf数组还有多少空间是未使用,这个值一般用在buf空间扩展,以及添加新值时会用到。不同于C字符串的扩张,SDS API在对SDS进行修改时,会先检查SDS的空间是否满足所需需求,若不满足,API会自动将SDS的大小扩展至所需空间.这样做的好处是不会有缓冲区的溢出.
buf的作用
SDS的API都是二进制安全(binary-safe)的,通俗的来说SDS的API通过某种机制,保证了读写字符串的时候不会损害其内容,因为在C语言中,“\0”表示了字符串的结束,出现这个字符,字符串就会被截断,造成错误的字符,而在sds中即使字符串里有“\0”,也不会被截断,除非是redis自己的结尾字符,保证了读写的一致性.虽然SDS是二进制安全的,但是它还是兼容了一部分C字符的特性.
简单示例
现在我们,往SDS保存madpudding,按照上述结构,存入字符的SDS的长度是10,而buf里的前10个字节分别保存madpudding 10个字符串.实际上buf里会有11个字符,sds还是会以\0,作为字符结尾.
SDS机制
重新分配内存
分配内存机制
小于1MB情况
如果对sds进行修改后,整体的长度小于1MB,那么redis分配的是和len属性同样的大小空间,以madpudding为例,是10(buf长度)+10(free空间)+1(结尾字符).
大于1MB情况
假如修改后整体长度大于20MB,则实际空间是20MB(buf长度)+1MB(free空间)+1(结尾字符).
为什么这样分配
为什么redis会为sds这样分配空间呢?假设在实际使用中,有个sds一直在增加,按上述分配法,则在n次扩展中,sds最多重新分配n次空间,要知道io是很消耗性能的,最多n次和n次,性能差距是非常大的.
惰性释放内存
假如sds的字符,一直在减少,那么sds会立马释放未使用的空间嘛?答案是否定的,sds只会在free中依次记录,等待将来使用。这样做的目的是避免了缩减字符而重新释放内存,并为将来可能有的增长提供了空间基础.当然sds提供了真正需要释放空间的命令,让开发者不用担心惰性释放造成空间浪费.