前言
???????? 最近在学习Redis相关的知识,在看Redis五种基本数据类型时,发现里边的字符串类型和以前C语言的不一样,他是Redis内部重新实现的一种数据类型--简单动态字符串(SDS)。C语言的字符串必须以‘\0’结尾,字符串的中间不能包含'\0',这些限制使得C语言字符串只能保存文本数据。二Redis的sds字符串除了C语言的文本字符串外,还可以保存图片、音频、视频、压缩文件等二进制数据。下面,我们看看这个神奇的SDS的数据结构、原理、及优点。
提示:以下是本篇文章正文内容,下面案例可供参考
一、Redis SDS是什么?
???????? simple dynamic string--简称SDS,即简单动态字符串。它可以保存C语言字符串,这种无需对字符串值进行修改的地方,如日志记录;还可以用于可修改的字符串值的情景,如Redis的数据库里包含字符串的键值对。
二、Redis SDS数据结构
本文的源码来自 redis-6.2.6\redis-6.2.6\deps\hiredis\sds.h
struct __attribute__ ((__packed__)) hisdshdr32 {
uint32_t len;
uint32_t alloc;
unsigned char flags;
char buf[];
};
len属性记录的是字符串的长度,不包含结尾的‘\0’。这是为了兼容C语言字符串,可以方便的重用C语言的一些库函数。 free属性记录sds字符串中剩余的空闲空间。正是因为sds中有预留的空间,在字符串扩展操作时,不用每次都申请内存,并拷贝,提高了操作效率。 buf里是实际的字符串保存的地方,他的内存长度为len+free+1。其中有效的字符串长度为len,len之后总是接着一个'\0'。这样,buf里面是C字符串时,可以使用C的字符串库进行操作buf。
三、Redis SDS优点
1、常数复杂度获取字符串长度;
sds结构中有len属性,所以我们取字符串长度时,不需要像C语言字符串那样,需要遍历一遍字符串,才能知道字符串的长度。
2、可以防止缓冲区溢出;
sds操作字符串扩展操作时,首先会判断free属性是否足够存放新增部分字符串,如果不够,会先扩展buf的空间,然后再执行字符串的扩展操作,所以sds的字符串扩展操作不会导致缓存区溢出。而C语言在字符串扩展时,strcat并不检查目标缓存区有足够的空间,所以有缓存区溢出风险,这些风险,都需要程序员来预防。
3、可以减少修改字符串时带来的内存重新分配的次数;
sds操作字符串时,只有free空间不足时,才会触发内存重新分配,扩展内存空间。它的扩展策略是:len小于1M时,扩展的内存空间等于len+1字节;len大于1M时,扩展的内存空间是1M+1字节。通过这种策略,可以避免字符串操作是频繁的景象内存扩展操作。这是C语言字符串不具备的性能优势。
4、采用惰性空间释放;
当进行字符串收缩操作时,并不释放多余的空间,而是把多出的空间记录进free属性,避免了内存重新分配,同时新增的空间可以方便以后字符串扩展操作时使用。
5、二进制安全;
C语言字符串必须以’\0’结尾,且字符串中间位置不能含有’\0’。而sds字符串不受这些限制,因为他记录的字符串长度保存在len属性,只要是len之内的内容,都算是字符串的值,而不是字符串结束标识符。sds除了可以保存文本字符串之外,还可以保存诸如图片、音频、视频、压缩文件等二进制文件。sds使用buf来保存字节数据的,而不只是字符串数据,所以它比C字符串更强大。
总结
????????Redis中使用了大量的数据结构,除了之前介绍的跳表及本文提到的简单动态字符串之外,还有双向列表、哈希表、集合等。我们可以通过开源项目,学习到非常多的基础知识,以及这些简单数据结构如何创造出一个性能优异的软件产品。
|