美文网首页Redis相关
Redis 简单动态字符(SDS)

Redis 简单动态字符(SDS)

作者: Oliver_Li | 来源:发表于2019-12-07 17:34 被阅读0次
    • 后续所有未标注版本的Redis源码都源于5.0

    简单动态字符串SDS

    • Redis里的字符串默认为sds类型,例如所有的key就都是sds。
    SDS的定义
    // V3.2之前
    struct sds {
     // 记录 buf 数组中未使用字节的数量
     int free;
     // 记录 buf 数组中已使用字节的数量
     int len;
     // 字节数组,用于保存字符串
     char buf[];
    };
    
    // V3.2之后,sdshdr16/sdshdr32同理
    struct __attribute__ ((__packed__)) sdshdr5 {
        unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
        char buf[];
    };
    struct __attribute__ ((__packed__)) sdshdr8 {
        uint8_t len; /* 已使用 */
        uint8_t alloc; /* 总长 */
        unsigned char flags; /* 3 lsb of type, 5 unused bits */
        char buf[];
    };
    
    • sds用到了柔性数组,数组放在结构体最后时,可以根据需要动态分配,如前面lenfree各需要4字节,申请16字节时,除去结束符\0的位置,剩下7字节就是buf的使用长度了,需要注意结束符\0不算到len中。
    • 以上展示了两个版本sds结构体代码,V3.2之前freelen各占4字节,比较浪费空间,最节省的办法就是按位算lenfree的个数,进而出现了sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64
    • 新版sds中,flags低3位就代表了sdshdrN中的某一个,3位就可以区分出5种结构,可以发现sdshdr5中没有len、alloc,由flags高5位表示lensdshdr8 sdshdr16 sdshdr32 sdshdr64就比较容易理解了,flags低3位和sdshdr5一样,高5位是空闲状态。
    SDS与C字符串的区别
    • 性能优化:记录后获取字符长度时,时间复杂度降到O(1),避免遍历。
    • 函数库兼容:SDS遵循C的惯例,结尾以'\0'结束,这样很多C的函数库避免重复。
    • 保证安全:有len字段不用依赖“/0”终止符,保证二进制安全。
    SDS拼接时扩容策略
    • sds有空余空间时直接扩容即可。空间不足时分两种情况,扩容后总长小于1M时按两倍扩容,大于1M时总长+1M扩容,最后根据长度重新选择结构sdshdrN并选择是否重新开辟空间。
    • 在《Redis运维与开发》中也提到,尽量减少sds的拼接操作,避免预分配造成空间浪费。

    相关文章

      网友评论

        本文标题:Redis 简单动态字符(SDS)

        本文链接:https://www.haomeiwen.com/subject/fxrugctx.html