Redis研究-1.简单动态字符串

本文介绍了Redis中SDS(Simple Dynamic String)的设计与优化策略,包括内存安全、字符串增长和缩短操作的优化,以及如何通过len和free属性提高字符串操作效率。

我们知道,在C字符串中,底层的实现是使用c字符数组来实现的,但是在高性能以及内存安全方面,使用底层的c字符串是满足不了的,举个简单的例子,如果你使用strcat(s,s1)函数,如果在操作之前不判断s的空间是否能够容纳s1的内容,那么就很有可能导致内存溢出,而导致操作失败,因此,为了满足性能及内存安全方面的要求,Redis实现了SDS。

SDS的定义是(位于sds.h):

struct sdshdr {

// buf 中已占用空间的长度
int len;

// buf 中剩余可用空间的长度
int free;

// 数据空间,默认是使用C字符串的空字符结尾的
char buf[];

};

其中每项的含义已经在注释中说明。

通过上面的定义,我们可以看到,sds与传统的c字符串做了几方面的优化:

在sds中,记录了“字符数组”的的长度len;

通过使用free可以实现预分配策略优化。

通过这两方面的优化,我们可以得到以下方面的提升:

在做需要设计到内存扩展方面的操作的时候,只要检查free属性,就可以很容易得到是否需要扩展内存,从而避免内存溢出;

在获取字符串长度方面,再也不用花费O(N)时间复杂度,只主要获得len属性就可以得到长度,时间复杂度变为O(1);

我们知道,C字符串和底层数组之间是有密切联系的,因此每次增加或者缩短一个C字符串,都会涉及到对内存的分配,但是使用sds的len属性和free属性,可以减少内存的重分配次数。

关于上面提到的减少内存重分配优化方面,Redis做了两方面的优化,一个是空间预分配和惰性空间释放。

空间预分配:这方面的优化主要是用于字符串的增长操作:当用SDS的API来修改一个SDS,且需要进行空间扩展的时候,程序首先会为SDS分配修改所必须的空间,其次,还会分配额外的使用空间,这里面有两个策略:

    当对SDS的内存进行修改后,SDS的长度已经超过1M了,那么Redis会自动的为这个SDS分配1M的free看空间;

    当对SDS的内存进行修改后,SDS的长度小于1M,那么,Redis会自动给这个SDS分配等同于len的free空间。

惰性空间释放:对于传统的C字符串,如果我们要缩短,那么就一定要释放对应的内存,否则会导致内存泄露,但是Redis中的SDS,会把这部分内存用free来记住,所以,可以不用马上释放,这部分内存可以供以后使用,当然,Redis也提供了相关释放的API。

 

此外,我们对于传统的C字符串,我们只能存储简单的文本字符串,为什么呢?因为在传统的字符串中,我们是使用空字符来判断这个字符串是不是结束了,因此在字符串的中间就不能使用特殊的字符。这给要在多场景应用下的Redis带来了弊端,因此,在Redis的SDS中,并不是用简单的空字符来判断一个buf是不是已经结束了,而是要使用len属性来判断是不是已经结束,因此,在Redis的SDS中的buf 是可以存储文本字符串之外的数据的,因此,在Redis的SDS中,buf更多的是称作一个字节数组。当然,SDS中的buf 也是使用空字符来作为这个串的结尾的,这是为了兼容一部分C字符串的操作函数。

文章转载自 开源中国社区[https://www.oschina.net]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值