Redis 阅读笔记-动态字符串

简单动态字符串(simple dynamic string)抽象模型, 简称SDS

SDS在Redis的应用场景

1、用来保存数据的字符串值
2、被用做缓冲区,如AOF模块的AOF缓冲区,客户端输入的缓冲区

SDS的定义

// sds.h/sdshdr结构表示的SDS值:
struct sdshdr {
    //所保存的字符串长度
    int len;
    //数组中未使用字节的长度
    int free;
    //字节数组,用于保存字符串
    char buf[];
}

SDS示例如下图:
SDS示例

SDS相比与C字符串的区别

1、获取C字符串长度,程序需遍历整个字符串,操作复杂度为O(N), 而SDS的在len属性中记录SDS本身的长度,获取SDS字符串的长度复杂度仅为O(1)。
2、SDS字符串可以杜绝缓冲区溢出。这是因为SDS API对SDS进行修改时,API会先简称SDS的空间是否满足所需修改的要求,若不满足,会自动将SDS扩展所需的大小,然后再执行修改操作。
3、减少字符串修改带来的内存重分配次数。SDS通过未使用空间解除了字符串长度和底层数组长度的关联:在SDS中,buf数组长度不一定是字符串加一, 数组里面可以包含未使用的字节,而这些字节的数量有SDS的free属性记录。
通过未使用空间,SDS实现了空间预分配和惰性空间释放两种优化策略。
1)空间预分配
SDS对空间进行扩展时,程序不仅为SDS分配修改,还会为SDS分配额外未使用的空间。分配未使用空间数量的公式如下:

若SDS的长度(len属性的值)小于1M,程序分配和len属性同样大小的未使用空间,此时len的值和free属性的值相同。
若SDS修改后,SDS的长度大于1M,那么程序将会分配1M未使用空间
在扩展SDS空间之前,SDS API会先检查未使用空间是否足够,如果足够,API会直接使用未使用空间,而无需执行内存重分配。通过这种预分配策略,SDS将连续增长N次字符串所需的内存分配次数从必定N次降低为最多N次。

2)惰性空间释放
惰性空间释放用于优化SDS字符串缩短操作。当SDS API需要缩短SDS保存的字符串,程序并不使用内存重分配来回收缩短后多出来的字节,而是使用free属性,将这些字节记录下来,方便将来在用。

4、二进制安全的
C字符串必须符合某中编码,并且除了字符串末尾外,字符串不能包含空字符,最先读入的空字符被误认为字符串的结尾,这使C字符串只能保存文本数据,不能保存图片,音频,视频,压缩文件这类的二进制数据。
SDS的API都是二进制安全的,所有的SDS API都会处理二进制方式来处理SDS存放在buf数组里的数据,程序不会对数据做任何限制,过滤或假设。
5、SDS兼容部分C字符串函数。

posted @ 2020-08-18 10:37  phper-liunian  阅读(91)  评论(0编辑  收藏  举报