您好,欢迎访问一九零五行业门户网

Redis中SDS简单动态字符串问题怎么解决

一、sds的结构 c语言没有string类型,本质是char[]数组;而且c语言数组创建时必须初始化大小,指定类型后就不能改变,并且字符数组的最后一个元素总是空字符 '\0' 。
以下展示了一个值为 redis 的 c 字符串:
redis没有直接使用c语言的字符串方式,而是构建了一种简单动态字符串(simple dynamic string, sds)的类型,redis中的字符串底层都是使用sds结构进行存储,比如包含字符串的键值对底层都是使用sds结构实现的。
sds结构定义在sds.h中
struct sdshdr{ int len;//sds保存的字符串长度 int free;//buf数组中未使用字节数量 char buf[];//字符数组,保存字符串}
最后一个字节保存了空字符'\0',保留了c字符串的规范,使得sds结构的字符串,可以重用一部分c函数库的函数。
二、为什么不使用c字符串主要是因为c字符串有以下缺点:
获取字符串长度时间复杂度为o(n):c字符串获取长度需遍历整个字符串,遇到'\0'空字符为止。如果在进行字符串追加操作时没有分配足够的内存,就会发生缓冲区溢出。 内存重分配:每次增长或者截短字符串,程序都要对保存c字符串的数组进行内存重分配操作,而内存重分配涉及复杂的算法,并可能需要执行系统调用,所以它通常比较耗时。 空字符问题:c字符串中间不能保存空格,否则程序遍历是会误认为是字符串的末尾。由于这一限制,c字符串只能用于存储文本数据,而不适用于保存二进制数据如图片、音视频和压缩文件等。
三、怎样解决c字符串问题  
1、sds通过len属性记录了sds长度,所以获取长度的时间复杂度为o(1),即strlen命令的时间复杂度是o(1)。
2、sds空间分配策略避免了缓冲区溢出:当对sds进行修改时,会先检查sds空间是否满足修改,不满足会自动扩展到所需大小,然后才执行修改。
3、较少修改字符串时内存重分配次数:sds中的free记录buf字节数组中未使用的字节。
redis通过free属性实现空间预分配、惰性空间释放两种优化策略。
空间预分配:当对sds进行增长操作时,程序不仅会分配修改所必须得空间,还会为sds分配额外的未使用空间。内存重分配次数在连续执行字符串增长操作时得以减少,这是通过预分配策略实现的。 惰性空间释放:当对sds进行截短操作时,程序并不会立即回收缩短后多出来的字节所占用的内存,而是使用free属性记录多出来的字节数,以供将来使用。未被使用的空间可能会在未来进行sds增长时派上用场,此时增长操作不一定需要执行内存重分配。
sds结构中的buf字节数组,是二进制安全的,不仅可以保存字符,也可以保存二进制数据。
sds保留了c字符串的惯例,将数据的末尾设置为空字符'\0',sds中之所以保留这一规范是可以重用c字符串函数库的一部分函数,例如追加字符串。
四、对字符串的进一步优化redis string的三种编码:
int 存储8个字节的长整型(long,2^63-1 ) embstr, embstr格式的sds (simple dynamic string) raw, raw格式的sds,存储大于44个字节的长字符串
int类型就是指的是数字,那么raw、embstr都代表的是字符串有什么异同吗,下面我们分析下。
图中展示了两者的区别,可以看到embstr将redisobject和sds保存在连续的64字节空间内,这样可以只需要一次内存分配,而对于raw来说,sds和redisobject分离,需要两次内存分配,而且占用更多的内存空间。
可以看到embstr在3.2+中使用了叫sdshdr8的结构,在该结构下,元数据只需要3个字节,而redis需要8个字节,所以总共64个字节,减去redisobject(16字节),再减去sds的原信息,最后的实际内容就变成了44字节和39字节。
当字符串小于等于 44 字节时,redis 就使用了嵌入式字符串的创建方法,以此减少内存分配和内存碎片。
下面这张图展示了 createembeddedstringobject 创建嵌入式字符串的过程:
总之,只要记住,redis 会通过设计实现一块连续的内存空间,把 redisobject 结构体和 sds 结构体紧凑地放置在一起。
这样一来,对于不超过 44 字节的字符串来说,就可以避免内存碎片和两次内存分配的开销了。
sds是redis中一种高效的字符串实现方式,它具有自动扩容、二进制安全、o(1)长度获取和修改等优点。在实际的应用中,sds可以帮助我们实现高效的字符串操作,同时也可以避免一些常见的字符串操作问题,比如缓冲区溢出等。通过深入了解sds的内部结构和实现原理,我们可以更好地理解redis的底层机制,进一步提升我们的redis应用能力。
以上就是redis中sds简单动态字符串问题怎么解决的详细内容。
其它类似信息

推荐信息