Redis实现原理(一)简单动态字符串

目录

SDS的定义

SDS与C字符串的区别

获取字符串的长度

杜绝缓冲区溢出

空间预分配

惰性空间释放

二进制安全

区别汇总

SDS API


Redis构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS作为Redis的默认字符串表示。

SDS的定义

struct sdshdr {
    // 记录buf数组中已使用字节的数量,不包括'\0'的长度
    // 等于SDS中保存的字符串的长度
    int len;

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

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

SDS与C字符串的区别

获取字符串的长度

C字符串不记录自身的长度信息, 获取字符串长度时会遍历字节数组, 直到遇到空字符为止. 复杂度为 O(N)

SDS直接通过 len 属性获取字符串长度. 复杂度为O(1)

杜绝缓冲区溢出

C字符串不记录自身长度, 修改字符串时不会判断本身是否拥有足够的内存空间, 当内存空间不足时, 则会造成缓冲区的溢出.

SDS对字符串进行修改时,先检查内存空间是否满足修改的需要, 若不满足, 则自动扩展SDS的内存空间. 所以使用SDS既不需要手动修改内存空间的大小, 也不会出现缓冲区溢出的情况.

空间预分配

  第一次创建字符串对象时, SDS不会分配冗余空间, 即 len = 0

  当SDS的API修改SDS时, 则会为其分配冗余空间.

  1. 当修改后的SDS的 len 属性小于1MB时, 则为其分配和 len 同样大小的冗余空间, 即 free = len, 此时 buf [ ] 的实际长度 = len(实际长度) + free(冗余空间) + 1(空字符)
  2. 当修改后的SDS的 len 属性大于等于1MB时, 则为其分配1MB的冗余空间.  buf [ ] 的实际长度 = len(实际长度) + free(1MB) + 1(空字符)

惰性空间释放

  SDS的API缩短SDS的字符串时, 不会立即使用内存分配回收缩短后多出来的字节, 而是记录在 free 属性中, 并等待将来使用.

二进制安全

  C字符串中的字符必须符合某种编码(比如ASCII),并且除了字符串的末尾之外,字符串里面不能包含空字符,否则最先被程序读入的空字符将被误认为是字符串结尾,这些限制使得C字符串只能保存文本数据,而不能保存像图片、音频、视频、压缩文件这样的二进制数据。

  SDS的API都是二进制安全的.所有SDS API都会以处理二进制的方式来处理SDS存放在buf数组里的数据,程序不会对其中的数据做任何限制、过滤、或者假设,数据在写入时是什么样的,它被读 取时就是什么样。

  这也是我们将SDS的buf属性称为字节数组的原因——Redis不是用这个数组来保存字符,而是用它来保存一系列二进制数据。

区别汇总

C字符串SDS
获取字符串长度的复杂度为O(N)获取字符串长度的复杂度为O(1)
API是不安全的,可能会造成缓冲区溢出API是安全的,不会造成缓冲区溢出
修改字符串N次必然需要执行N次内存重新分配修改字符串N次最多需要执行N次内存重新分配
只能保存文本数据可以保存文本或者二进制数据
可以使用所有<string.h>库中的函数可以使用一部分<string.h>库中的函数

SDS API

函数作用时间复杂度
sdsnew创建一个包含给定C字符串的SDSO(N)
sdsempty创建一个不包含任何内容的SDSO(1)
sdsfree释放给定的SDSO(N)
sdslen返回SDS的已使用空间字节数O(1)
sdsavail返回SDS的未使用空间字节数O(1)
sdsdup创建一个给定SDS的副本(copy)O(N)
sdsclear清空SDS保存的字符串内容O(1)
sdscat将给定C字符串拼接到SDS字符串的末尾O(N)
sdscatsds将给定SDS字符串拼接到另一个SDS字符串的末尾O(N)
sdscpy将给定的C字符串复制到SDS里面,覆盖SDS原有的字符串O(N)
sdsgrowzero用空字符将SDS扩展至给定长度O(N)
sdsrange保留SDS给定区间内的数据,不在区间内的数据会被覆盖活清除O(N)
sdstrim接受一个SDS和一个C字符串作为参数,从SDS左右两端分别移除所有在C字符串中出现过的字符O(M*N)
sdscmp对比两个SDS字符串是否相同O(N)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值