Redis设计与实现——数据结构与对象(一)

本文深入解析了Redis中的简单动态字符串(SDS),探讨了其相对于C字符串的优势,包括常量复杂度获取长度、防止缓冲区溢出、减少内存重分配、二进制安全性和兼容C字符串函数。同时,文章详细介绍了SDS的结构定义和API函数,如sdsnew、sdsfree、sdscat等,以及它们的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis设计与实现——数据结构与对象(一)

1、 简单的动态字符串

  1. sds用途

    • 实现字符串对象

    • 在Redis程序内部用作char* 类型的替代品(why?)

      char*类型的功能单一,抽象的层次太低,并且不能高效地支持Redis常用的操作(比如追加操作和长度计算操作)

  2. sds的定义

    typedef char *sds;
    
    
    struct sdshdr {
    
        // buf 已占用长度
        int len;
    
        // buf 剩余可用长度
        int free;
    
        // 实际保存字符串数据的地方
        char buf[];
    };
    
  3. SDS与C字符串的区别

    • 常量复杂度获取字符串的长度

    • 杜绝缓冲区溢出

      除了获取字符串长度的复杂度高除外,C字符串不记录自身长度带来的另一个问题是容易造成缓冲区溢出

    • 减少修改字符串时带来的内存重新分配次数

      • 空间预分配(不仅仅会分配SDS分配修改必须要的空间,还会为SDS分配额外的未使用的空间)
      • 惰性空间的释放:当SDS的API需要缩短SDS保存的字符串时,程序不立即内存重新分配,而是使用free特性将字节数记录起来以便以后使用
    • 二进制安全:c字符串中的字符必须符合某种编码,除去某位之外,不得包含任何空格,否则会被认为是某位,故C字符串智能保存文本,而不能保存图片、音频、视频、压缩文件这样的二进制数据

    • 兼容部分C字符串函数

      遵循C字符串以空字符结尾的管理

  4. SDS的API

    函数作用算法复杂度
    sdsnewlen创建一个指定长度的 sds ,接受一个 C 字符串作为初始化值O(N)O(N)
    sdsempty创建一个只包含空白字符串 ""sdsO(1)O(1)
    sdsnew根据给定 C 字符串,创建一个相应的 sdsO(N)O(N)
    sdsdup复制给定 sdsO(N)O(N)
    sdsfree释放给定 sdsO(N)O(N)
    sdsupdatelen更新给定 sds 所对应 sdshdr 结构的 freelenO(N)O(N)
    sdsclear清除给定 sds 的内容,将它初始化为 ""O(1)O(1)
    sdsMakeRoomForsds 所对应 sdshdr 结构的 buf 进行扩展O(N)O(N)
    sdsRemoveFreeSpace在不改动 buf 的情况下,将 buf 内多余的空间释放出去O(N)O(N)
    sdsAllocSize计算给定 sdsbuf 所占用的内存总数O(1)O(1)
    sdsIncrLensdsbuf 的右端进行扩展(expand)或修剪(trim)O(1)O(1)
    sdsgrowzero将给定 sdsbuf 扩展至指定长度,无内容的部分用 \0 来填充O(N)O(N)
    sdscatlen按给定长度对 sds 进行扩展,并将一个 C 字符串追加到 sds 的末尾O(N)O(N)
    sdscat将一个 C 字符串追加到 sds 末尾O(N)O(N)
    sdscatsds将一个 sds 追加到另一个 sds 末尾O(N)O(N)
    sdscpylen将一个 C 字符串的部分内容复制到另一个 sds 中,需要时对 sds 进行扩展O(N)O(N)
    sdscpy将一个 C 字符串复制到 sdsO(N)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值