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

咱们知道,在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字符串作了几方面的优化: 内存

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

  2. 经过使用free能够实现预分配策略优化。 扩展

经过这两方面的优化,咱们能够获得如下方面的提高: 程序

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

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

  3. 咱们知道,C字符串和底层数组之间是有密切联系的,所以每次增长或者缩短一个C字符串,都会涉及到对内存的分配,可是使用sds的len属性和free属性,能够减小内存的重分配次数。

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

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

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

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

  2. 惰性空间释放:对于传统的C字符串,若是咱们要缩短,那么就必定要释放对应的内存,不然会致使内存泄露,可是Redis中的SDS,会把这部份内存用free来记住,因此,能够不用立刻释放,这部份内存能够供之后使用,固然,Redis也提供了相关释放的API。

     

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

相关文章
相关标签/搜索