Redis-SDS-创新互联

本文你能得到:

专注于为中小企业提供做网站、成都网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业东西湖免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

1 SDS基本介绍 。

2 SDS与 C语言传统字符串的区别,为什么使用SDS。

3 SDS的结构和策略详解。

1 SDS 是什么?用来做什么?

1.1 ​ Redis没有直接使用C语言传统的字符串表示(以空字符结尾的字符数组),而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS用作Redis的默认字符串表示。

1.2 在Redis的数据库里面,包含字符串值的键值对在底层都 是由SDS实现的。

2 SDS结构:

2.1类

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

2.2图

2.3 讲解

free 用于存储buf数组 剩余可用空间

len用于存储已用空间

buf 字节数组用于存储内容

2.4 问题

为什么数组最后 '\0' 空结尾?

请看3.1

3 char数组介绍的缺点

3.1 char 介绍

char 数组在 写入时候会分配内存 ,比如写入 Redis 就会分配6个存储空间,如图

这样在char读取的时候,首先会根据 内存指针找到开头的R 然后到 \0 结束,如果么有\0 char就不知道什么时候结束,但为啥SDS也要这样呢,因为能复用string.h等对字符串操作的工具类。 

缺点1 缓冲区溢出。

举例当两个char <string.h>/strcat函数可以将src字符串中的内容拼接到dest字符串的末尾:

char *strcat(char *dest, const char *src);

如果dest没有分配足够的内存空间,就会导致超出 dest 内存空间的部分 被写上src的数据,超出的部分可能分配给了其他变量,所以会导致其他变量数据错误,缓冲区溢出。

缺点2 内存泄漏

如果通过函数 删除了char数组中的一些数据,如果么有重新分类空间,会导致内存泄漏,删除的部分将不会被使用。

缺点3 重新分配地址

所以每次操作char都需要重新分配内存空间,来解决字符增加导致的缓冲区溢出,和减少字符串导致的内存泄漏,这样每次分配内存就有很大的成本,不适合redis这么频繁的操作。

缺点4 获取数组长度时间复杂度O(N)

如果要获取字符产股 需要循环每一个字符计数,时间复杂度O(N)) 而 SDS只需要返回len就可以时间复杂度O(1)

总结:

1 如果程序执行的是增长字符串的操作,比如拼接操作(append),那么在执行这个操作之前,程序需要先通过内存重分配来扩展底层数组的空间大小——如果忘了这一步就会产生缓冲区溢出。

2 如果程序执行的是缩短字符串的操作,比如截断操作(trim),那么在执行这个操作之后,程序需要通过内存重分配来释放字符串不再使用的那部分空间——如果忘了这一步就会产生内存泄漏。

4 SDS如何解决内存以上问题

4.1 空间预分配解决缓冲区溢出问题,避免频繁分配内存,代价是多一些有可能不会被使用到的空间浪费。

策略1

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

策略 2

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

4.2 惰性空间释放可以解决内存泄漏问题,避免频繁分配内存,缺点也是空间浪费。

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

5 SDS 二进制安全

例如存了"1234\0123"   \0会被读成结束

redis通过len来表示字符串长度,不会因为中间插入了\0就返回错误结果。

6 C字符串和SDS之间的区别总结

Redis只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(Simple DynamicString,简单动态字符串)作为字符串表示。

比起C字符串,SDS具有以下优点:

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

2)杜绝缓冲区溢出。

3)减少修改字符串长度时所需的内存重分配次数。

4)二进制安全。

5)兼容部分C字符串函数。

---chenchen

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章标题:Redis-SDS-创新互联
文章URL:http://scyanting.com/article/dipjdh.html