简单动态字符串SDS

  • 简单动态字符串(simple dynamic string):

    • redis虽然说是用C语言重写的,但它也进行了一些创新,自己构建了简单动态字符串SDS,从名字也看得出来有别于以空字符结尾的字符数组(C字符串)

    • reids中只有在一些无需对字符串修改的地方,才会去用C字符串。如一些日志的打印…

    • 而在一个可能被修改的字符串的时候,底层会去用SDS实现。如数据类型为字符串的key或value…

    • 此外,SDS还被用作缓冲区。如AOF缓冲区和客户端状态的输入缓冲区…

    • SDS的定义:

      • 用一个结构体来表示一个SDS值:

        struct sdshdr {
            //已使用的字节数量
            int len;
            //未使用的字节数量
            int free;
            //用来保存字符串的字节数组
            char buf[];
        }
        
      • SDS遵循了C语言字符串以空字符结尾的惯例,但保存空字符的一个字节不被len计算在内,所以这一字节对使用者来说就是透明的

      • 那么这么做的目的是什么? SDS可以直接重用一部分C字符串函数库的函数

    • SDS和C字符串的区别:

      1. 获取自身长度的时间复杂度:

        • SDS只需查len就知道自身长度,时间复杂度为O(1)
        • C字符串需要去遍历自身字节数组,时间复杂度为O(n)
        • 由此看,用SDS在查询自身长度时,性能得到了提高
      2. SDS可以杜绝缓冲区溢出的问题:

        • C字符串在一些拼接字符串的情况下,如果忘了检查剩余空间,可能会引起缓冲区溢出
        • 而SDS的API会在修改SDS时自动进行检查free和拓展等操作,所以SDS既方便又安全
      3. SDS减少了修改字符串带来的内存重分配次数:

        • C字符串的长度和底层数组长度之间存在一个字节的关联性,所以每次修改字符,都需要对数组进行一次内存重分配去拓展或释放空间

        • 内存分配涉及复杂的算法,并且可能需要执行系统调用,所以它通常比较耗时

        • SDS通过使用free解除了字符串长度和底层数组长度的关系,通过这个未使用空间,SDS实现了空间预分配和惰性空间释放两种优化策略,可以减少了修改字符串带来的内存重分配次数

          1. 空间预分配:用于优化SDS增长的操作,拓展空间不仅为SDS分配修改所需的空间,还会分配额外的未使用空间。

            1. 如果SDS修改后的长度(len)< 1MB(1MB等于1048576字节),那么程序将分配和len一样大的未使用空间。即len = x byte,free = x byte,buf数组有(2x + 1)byte长
            2. 如果SDS修改后的长度(len)>= 1MB,那么程序将分配和1MB的未使用空间。即len = 30MB, free = 1MB,buf数组有(31MB + 1byte)长
            3. 以上两种情况皆是基于free不足的条件,free如果多的很,那还分配个毛啊
            4. 空间预分配的意义:SDS将连续增长N次字符串所需的内存重分配次数从必定N次控制在最多N次
          2. 惰性空间释放:用于优化SDS缩短的操作,程序不立即使用内存重分配来回收缩短后多出来的字节,而是使用free将这些字节数量记录,等待将来使用

          • 与此同时,SDS提供了相应的API,让我们可以在有需要时,真正释放未使用的空间,不用担心此策略会造成内存浪费
          • 惰性空间释放的意义:SDS避免了缩短字符串时所需的内存重分配操作,并为将来的增长操作提供了优化
      4. SDS二进制安全

        • C字符串内部不能有空格,防止误认为是末尾,限制它只能保存文本数据,不能储存流媒体文件
        • SDS的API都是二进制安全的,,所有SDS API都会以处理二进制的方式处理SDS存放在buf数组里的数据,程序不会对其中的数据做任何限制、过滤、假设,数据在写入的时候是什么样子,读取的时候就是什么样子
        • 使用SDS保存内部空格的数据是没问题的,因为SDS是通过len来判断是否结束,而不是空字符
      5. SDS兼容部分C字符串函数(之前也谈到了SDS末尾也保留了空字符,只是没有纳入len,给放进buf字节数组了)

    • 总结:

      在这里插入图片描述

  • 47
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值