zoukankan      html  css  js  c++  java
  • Redis数据结构-简单动态字符串(SDS)

    1. 简介

    Redis没有使用C中默认的字符串(字符数组),而是自己构建了一个简单动态字符串(SDS)的抽象类型,并且作为默认的字符串。

    • Redis中会使用C中的字符串作为字符常量,用在无需修改的地方,如日志;
    • 当字符串会被修改时,就是使用SDS;
    • 此外,SDS还会被用作缓冲区。

    2. 定义

    sds.h/sdshdr 结构体表示一个SDS值:

    struct sdshdr {
        unsigned int len;
        unsigned int free;
        char buf[];
    };
    

    相比普通的C字符串,SDS的优点在于:

    • 能够通过len字段方便的知道字符串长度;
    • 通过free字段能方便知道缓存区剩余空间;
    • 同样字符串buf以''结尾,能够与print等C中函数接口通用;
    • 杜绝缓冲区溢出(SDS会先进行检查,空间不够会进行扩展)。
    • 二进制安全。
      在使用SDS API的情况下,不要手动修改len和free字段,它们的维护是API内部自动进行的。

    3. 内存优化策略

    3.1 空间预分配

    在使用SDS API进行字符串修改需要扩容时,不仅会分配修改所必须的空间,而且还会分配额外的未使用空间。总体策略:

    • 如果修改后的SDS长度(len字段)小于1MB,那么程序会分配同len相同的未使用空间,即free=len,实际长度是free+len+1=2len+1;
    • 如果修改后的SDS长度(len字段)大于1MB,那么程序会分配1MB的未使用空间。

    通过空间预分配,可以减少内存分配次数。

    3.2 惰性空间释放

    释放策略是:弹药使用API缩短SDS字符串时,程序并不会回收多出来的字节,而是使用free字段记录下来,以等待将来被使用。
    通过惰性空间释放,可以减少内存回收的次数,未回收的内存可以继续用于字符串的存储。
    如果要回收内存,SDS提供了相应的API。

    4. 特点

    4.1 二进制安全

    虽然SDS的buf保存了C的结尾的约定,但是它实际内容其实是由len字段决定,因此存储音视频等二进制数据是没有问题的,不用对数进行任何过滤操作。

    SDS也因此被称为字节数组--保存二进制数据。

    4.2 兼容部分C函数

    SDS仍然遵循C字符串以空白字符结尾的惯例,因此它也能使用C字符串中<string.h>部分函数。
    如stacat、strcmp等。

    区别:

    1. C字符串只能保存文本数据,而SDS可以二进制数据;
    2. C字符串API操作可能会导致缓冲区溢出,而SDS不会;
    3. SDS只能使用部分C函数;
    4. SDS获取字符串长度的时间复杂是O(1),而普通C字符串是O(n);
    5. 空间扩展,SDS会进行预分配,实际分配次数会比C字符串少。
  • 相关阅读:
    ACM学习历程—HDU1719 Friend(数论)
    封装的方法
    MySql-rules
    MySql
    java深入探究07-jsp
    java深入探究06
    Jquery
    Ajax
    java深入探究05
    Oracle——索引,序列,触发器
  • 原文地址:https://www.cnblogs.com/xl2432/p/12719315.html
Copyright © 2011-2022 走看看