redis设计与实现读书笔记(第一章)

Redis设计与实现读书笔记(第一章)

一:内部数据结构与对象

1.sds的定义:

Struct sdshdr{

//记录buf数组中已使用的字节的数量 保存字符串的长度

Int len;

//数组中未使用的字节的数量

Int free;

//字节数字,用于保存字符串

Char buf[]

}

 

SDS遵循C字符串以空字符结尾。

2.SDSC字符串的区别

C语言的使用长度是N+1的字符数组来表示长度为N的字符串。

C字符串不能记录自身的长度,所以获取C字符串的长度需要编目整个字符串,这个操作的复杂度为ON.

 

C 字符串不同, 因为 SDS len 属性中记录了 SDS 本身的长度, 所以获取一个 SDS 长度的复杂度仅为 O(1)

举个例子, 对于图 2-5 所示的 SDS 来说, 程序只要访问 SDS len 属性, 就可以立即知道 SDS 的长度为 5 字节。

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

C 字符串不同, SDS 的空间分配策略完全杜绝了发生缓冲区溢出的可能性: 当 SDS API 需要对 SDS 进行修改时, API 会先检查 SDS 的空间是否满足修改所需的要求, 如果不满足的话, API 会自动将 SDS 的空间扩展至执行修改所需的大小, 然后才执行实际的修改操作, 所以使用 SDS 既不需要手动修改 SDS 的空间大小, 也不会出现前面所说的缓冲区溢出问题。

总结:

2-1 C 字符串和 SDS 之间的区别

SDS

C字符串

获取字符串长度的复杂度为  

获取字符串长度的复杂度为  

API 是安全的,不会造成缓冲区溢出。

API 是不安全的,可能会造成缓冲区溢出。

修改字符串长度 N 次最多需要执行 N 次内存重分配

修改字符串长度 N 次必然需要执行 N 次内存重分配。

可以保存文本或者二进制数据。

只能保存文本数据。

可以使用一部分 <string.h> 库中的函数。

可以使用所有 <string.h> 库中的函数。

 

3.SDS API

函数

作用

时间复杂度

 

sdsnew

创建一个包含给定 C 字符串的 SDS 。

O(N) , N 为给定 C 字符串的长度。

sdsempty

创建一个不包含任何内容的空 SDS 。

O(1)

sdsfree

释放给定的 SDS 。

O(1)

sdslen

返回 SDS 的已使用空间字节数。

这个值可以通过读取 SDS 的 len 属性来直接获得, 复杂度为 O(1)

sdsavail

返回 SDS 的未使用空间字节数。

这个值可以通过读取 SDS 的 free 属性来直接获得, 复杂度为 O(1)

sdsdup

创建一个给定 SDS 的副本(copy)。

O(N) , N 为给定 SDS 的长度。

sdsclear

清空 SDS 保存的字符串内容。

因为惰性空间释放策略,复杂度为  。

sdscat

将给定 C 字符串拼接到 SDS 字符串的末尾。

O(N), N 为被拼接 C 字符串的长度。

sdscatsds

将给定 SDS 字符串拼接到另一个 SDS 字符串的末尾。

O(N) , N 为被拼接 SDS 字符串的长度。

sdscpy

将给定的 C 字符串复制到 SDS 里面, 覆盖 SDS 原有的字符串。

O(N), N 为被复制 C 字符串的长度。

sdsgrowzero

用空字符将 SDS 扩展至给定长度。

O(N) , N 为扩展新增的字节数。

sdsrange

保留 SDS 给定区间内的数据, 不在区间内的数据会被覆盖或清除。

O(N), N 为被保留数据的字节数。

sdstrim

接受一个 SDS 和一个 C 字符串作为参数, 从 SDS 左右两端分别移除所有在 C 字符串中出现过的字符。

O(M*N) , M 为 SDS 的长度, N 为给定 C 字符串的长度。

sdscmp

对比两个 SDS 字符串是否相同。

O(N) , N 为两个 SDS 中较短的那个 SDS 的长度。

在线阅读地址:

http://redisbook.com/preview/sds/different_between_sds_and_c_string.html#id2

猜你喜欢

转载自blog.csdn.net/wagnteng/article/details/52711877