您的位置:首页 > 数据库 > Redis

Redis之简单动态字符串

2017-04-28 22:55 274 查看

SDS的介绍

Redis中字符串并没有使用C语言传统的字符串,而是构建了一种名为简单动态字符串(SDS),SDS是Redis的默认字符串标识。

Redis里面的C语言字符串用在一些无需对字符串值进行修改的地方,例如打印日志
redisLog(REDIS_WARNING,"redis is now ready to exit");


当Redis需要的是可以被修改的字符串值时,使用SDS来表示字符串值

redis> SET msg "hello word"
//msg作为key,SDS
//hello word 作为value ,SDS


SDS的定义

struct sdshdr{
int len;// 记录buf数组中已使用的字节的数量 == SDS中字符串长度
int free;//记录buf中未使用字节的数量
char buf[];//字节数组,用于保存字符串
}
//buf中保存着字符串值,以 \0结尾 ,但是 len中不包含\0
//例如保存字符串reids 则 len长度为5


SDS可以直接重用一部分C字符串函数库里面的函数,

//获取SDS的指针s
printf("%s",s->buf);


SDS与C字符串的区别

C语言使用的这种简单的字符串表示方式,并不能满足Redis对字符串在安全性、效率以及功能方面的要求,因此,SDS比C字符串更适用于Redis。

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

(直接通过len来获取时间复杂度为O(1),然而C中要循环时间复杂度为(O(n)))

2.杜绝缓冲区溢出

char *strcat(char *dest,const char *src);
//dest的空间大小并不知道,src长度可能过大,造成dest原本空间地址相连接的外部覆盖
//,造成内容被意外修改,


SDS会先检查是否满足修改所需的要求,如果不满足,则空间扩展至所需大小,然后再执行修改操作。

SDS的空间扩展策略,减少修改字符串时带来的内存重分配次数

(SDS实现了空间预分配和惰性空间释放两种优化策略)

(1)空间预分配

-在对SDS修改是,不仅对SDS分配修改所必须要的空间,还会增加额外未使用空间

当长度(len)小于1MB时,len长度和free长度是相同的

(buf实际长度 = len + free + 1(\0) len == free)

当长度(len)大于等于1MB是,程序会分配1MB的未使用空间

(buf实际长度 = 30MB + 1MB + 1byte)

(2)惰性空间释放

当SDS缩短SDS保存的字符串时,程序不会立即重分配来回收缩短后多出来的字节,而是使用free属性将这些数量记录起来,并等待将来的使用。

3.二进制安全

C语言字符串除了末尾是空字符外,其他地方不能是空字符,否则出错。

将导致C字符串只能保存文本数据,不能保存成图片,视频,压缩文件等二进制数据。

SDS的buf属性成为字节数组的原因是:

Redis不是用这个数组来保存字符,而是用它来保存一系列二进制数据。

SDS使用len属性的值而不是空字符来判断字符串是否结束!

C字符串和SDS之间的区别

C字符串SDS
获取字符串长度的复杂度为O(n)获取字符串长度的复杂度O(1)
API是不安全的,可能造成缓冲区溢出API是安全的
修改字符串长度N次,必然要执行N次内存重分配修改字符长度N次,对多执行N次内存重分配
只能保存文本数据可以保存文本或者二进制数据
可使用
<string.h>
库中的函数
可使用一部分
<string.h>
库中的函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  redis