Redis(一) 简单动态字符串SDS

一.概述

       在Redis中只将C字符串用于一些无需对字符串值进行修改的地方(常量),如日志打印,而其它需要修改(比如底层的键-值对存储)的地方都使用了自己构建的SDS(简单动态字符串)进行存储。

 

二.SDS结构

      SDS是一种对C字符串的封装,其结构体如下:

struct sdshdr{
    // 记录buf数组中已使用的字节数(不含末尾的空字节'\0')
    int len;

    // 记录buf中未使用字节的数量
    int free;

    // 字节数组,用于保存字符串
    char buf[];
};

      其中buf中存储的字符串采用C字符串的风格,以'\0'结尾,以便重用部分C字符串函数,比如:printf("%s", sds->buf),字符串比较函数等。

【注】:有些类似于TCP/IP中的mbuf.

 

三.SDS较C字符串的优点

1.获取字符串长度的时间复杂度

      由于C字符串并不记录长度,因此需要进行遍历,直至遇到'\0',其时间复杂度为O(N),而SDS中由于记录了字符串长度,因此时间复杂度为O(1)。

2.杜绝缓冲区溢出

     C字符串在拼接时并不负责检查和维护字符串的长度,这一切都依赖于程序用事先开辟足够大的缓冲区,否则将会造成溢出并可能覆盖掉后面的内存中的原先内容。同样在裁剪时,也依赖程序员重新调整大小。

     SDS结构及其相应API会自动管理这些情况,并通过空间预分配(类似于vector的分配策略)和惰性空间释放两用策略优化效率

  • 空间预分配:该分配策略用于优化SDS的字符串增长效率,当需要扩展空间时,SDS的API不仅分配所需大小的空间,还将预先分配一定的额外空间,以防止每次扩展时都要进行内存扩展。其预先分配内存的策略是:若SDS的长度(len)小于1M,则额外预分配空间大小与len值相同,若SDS的长度(len)大于1M,则分配1M的额外未使用空间。

          预分配源码如下:

#typedef char *sds;
sds sdsMakeRoomFor(sds s, size_t addlen) {
    struct sdshdr *sh, *newsh;
    size_t free = sdsavail(s);
    size_t len, newlen;

    if (free >= addlen) return s;
    len = sdslen(s);
    sh = (void*) (s-(sizeof(struct sdshdr)));
    newlen = (len+addlen);
    // - 当字符串增长后的长度小于1M时,按2倍大小申请
    // - 否则预扩充1M
    if (newlen < SDS_MAX_PREALLOC) //#define SDS_MAX_PREALLOC (1024*1024)
        newlen *= 2;
    else
        newlen += SDS_MAX_PREALLOC;
    newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
    if (newsh == NULL) return NULL;

    newsh->free = newlen - len;
    return newsh->buf;
}
  • 惰性空间释放:该策略用于缩短SDS字符串的长度,当要对SDS中的字符串进行缩短操作时,并不立即回收空闲出来的字节,而是将其记录在free中,待需要时,通过相应的SDS的API进行空间释放。

3.二进制数据存储

     C字符串字符需要符合ASCII编码,在字符串中只可在尾部出现空字符'\0',若在中间出现则无法读取到后面的字节,因此只能保存一些ASCII编码编码的文本数据,而对于图片,音频等数据便无法保存。

     而SDS记录了字符串长度,且SDS的API都是二进制安全的(不会由于遇到某种特殊字符而无法处理,因为不以'\0'求长度),不会对其中数据做任何限制,过滤等,保证了数据写入与读取时的一致性。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值