您的位置:首页 > 数据库 > Redis

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

2019-02-06 23:54 232 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_23464961/article/details/86769921

目录

SDS的定义

SDS与C字符串的区别

获取字符串的长度

杜绝缓冲区溢出

空间预分配

惰性空间释放

二进制安全

区别汇总

SDS API

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

SDS的定义

[code]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

3ff7
函数 作用 时间复杂度
sdsnew 创建一个包含给定C字符串的SDS O(N)
sdsempty 创建一个不包含任何内容的SDS O(1)
sdsfree 释放给定的SDS O(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)

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: