最近在找工作,一直问底层实现,接下来记录一下redis的底层实现。今天说下 简单动态字符串,也就是SDS。
SDS是redis的核心数据。虽然简单,但特别重要。包含字符串的键值对的数据类型都是由SDS实现的,而不是简单的一个C语言字符串,下面看一下这个SDS是什么样子的。
1.SDS数据结构
struct sdshdr{
//字符串长度
int len;
//buf数组中未使用的字节数量
int free;
//字节数组,用于保存字符串
char buf[];
}
如上,其实只有len,free,buf。
2.而为什么不用C字符串,而用SDS
下面说几个原因
①可以直接获取字符串的长度。SDS用len直接表示了,而C语言字符串需要遍历计数,时间复杂度是 O(1)与O(N)的区别。
②可以减少动态申请内存次数。因为有free的存在,可以在这里进行内存的增删。
③二进制安全,由于C字符串结尾是空字符串,所以如果有图片之类的压缩字符文件,在C语言中看到空字符串就认为结束了,这样不能标志二进制数据。而SDS是用len来表示字符串结束。
3.SDS具体使用简单介绍
①例如
redis> SET msg "hello world"
在这条简单的命令中, msg是一个msg对象,hello world也是一个SDS对象。这对象就如上面所定义的结构体那样。
②例如
redis> RPUSH fruits " apple" "banana" "cherry"
在这条命令中,fruits 是一个SDS对象
apple ,banana,cherry 也分别代表一个SDS对象
③其他方面应用简介
AOF缓冲区,客户端状态输入缓冲区都是由SDS实现的
4.C字符串与SDS区别
①获取字符串长度复杂度为O(N);获取字符串长度复杂度为O(1)
②API是不安全的,可能造成缓冲区溢出;API是安全的,不会造成缓冲区溢出
③修改字符串长度必然需要执行N此内存重分配;修改字符串长度N次最多需要执行N次内存重分配。
④只能保存文本数据;可以保存文本或二进制数据
⑤可以使用<string.h>库所有函数;可以使用部分<string.h>库中的函数
参考书籍:《Redis设计与实现》黄建宏 著
PS:只是为了学习记录,如果有侵权告知,立马删除。如果有错误,请留言,我尽快改正。