【Redis学习笔记】1.简单动态字符串(SDS)

背景:

Redis底层虽然是用C语言实现的,但是没有直接是用C语言传统的字符串表示,而是基于字符数据实现一个简单动态字符串(simple dynamic string, SDS),更加适用于Redis的存储、性能、安全要求。

结构:

一.SDS结构定义:

sds{
    int len; //sds字符串的长度(不包括空字符)
    int free; //sds结构中未使用的数组长度
    char buf[]; //存储字符串的数组

}

其中:

1.SDS的底层结构和C语言字符串类似,也是以空字符结尾。好处是为了兼容C语言中的字符串函数,避免重复造轮子

2.SDS结构中用len表示字符串长度,但是不包括空字符,空字符为系统自动分配,对上层透明

3.通过free字段表示该SDS字符串中还剩余多少可用空间,提高字符串修改的性能

结构图如图:

【Redis学习笔记】1.简单动态字符串(SDS)_第1张图片

二、对比C语言字符串

1.常数级获取字符串长度

C语言中的字符串获取长度,需要遍历整个字符数组获取数组的长度;而简单动态字符串的结构中通过len字段来表示字符串的长度。注:SDS中字符串的长度与存储字符的数组长度是不一样的,字符串的长度小于等于字符数组的长度

2.SDS结构避免了内存溢出

C语言中的字符串处理需要开发者自己处理好内存分配,自己解决内存问题。而SDS通过free、len、buf这三个字段来实现内存空间检查,避免字符串处理过程中的内存溢出和内存遗漏问题。

当需要对SDS进行修改的时候,会检查free大小是否满足要求,如果不满足,则通过自动扩容来扩充。

3.减少内存重分配次数

C语言字符串中对字符串进行修改的时候,都需要对内存空间进行重新分配,以免出现内存问题,例如:

如果增长字符串,则需要重新分配一份内存空间,否则在拼接过程中会产生缓冲区溢出

如果缩减字符串,则需要对原先的字符所占空间进行回收,否则会产生内存泄漏问题

而SDS通过未使用空间来避免频繁的对内存进行操作,提高字符串处理的性能,其优化策略有两种:空间预分配与惰性空间释放。

1).空间预分配:如果增长字符串的时候,空闲空间不满足要求,需要进行扩展,其扩展方式如下:

  • 如果修改后的SDS长度即len的值小于1MB(1024个字节),那么重新分配len值大小的未使用空间,此时len值和free值大小相同
  • 如果修改后的SDS长度即len的值大于1MB(1024个字节),那么每次回分配1MB的未使用空间
  • 注:字符串数组的长度为:修改后的长度+重新分配长度+1byte

2)惰性空间释放:如果缩短字符串,需要对字符串数组中多余的内存进行回收,并且更新free值,将回收的内存标记为未使用空间,方便下次使用

4.二进制安全

C语言字符串中的字符必须满足某种编码,并且字符中不能包含空格,故C语言字符串只能用来保存文本数据,无法保存图片、视频类的二进制数据;而SDS结构是二进制安全的,其底层的存储结构实际上是基于字节数组存储的,不会对存储的数据进行过滤、限制,保证进去和出来的数据都是一样的

5.兼容C语言字符串处理函数

因为SDS中的字节数组和C语言的字符串存在类似的结构,并且都是以\0结尾,所以字符串处理函数可以兼容处理SDS结构的数据

小结

Redis通过重新定义字符串底层存储结构,同时兼容C语言字符串的特性,提高Redis字符串的处理性能,提供快速存取能力

 

你可能感兴趣的:(Redis)