redis虽说是用C语言开发的,但是redis考虑了性能、安全性、效率性、功能等要,redis底层存储字符串实现,自己实现了名为简单动态字符串(Simple dynamic string)简称SDS的结构来存储字符串,这个结构有int len(当前字符串长度), int free(未使用的字符串长度可以说是缓冲), char buf[](存储的字符串数组)这几个变量。
接下来我们开始分析C语言默认字符串和SDS字符串的区别以及redis为什么要使用SDS。
1、C语言的字符串存储并不能记录自身字符串长度,且在内存中实现的方式是|r|e|d|i|s|\0 最后的'\0'表示C语言的结束符,每次调用strlen方法取字符串长度无可避免得去搜索'\0'结束的字符串从而使复杂度变成O(N),redis作为一个高性能的代名词是无法容忍这个缺陷的,所以SDS结构的len变量就有用了直接可以知道这个变量大小是多少,从而使软件的复杂度变成O(1)。
2、C语言的2个字符串在连接得时候容易发生内存溢出问题,比如现在有2个连续的C字符串 a(len=6),b(实际长度8)在内存中分配的地址如下:
|r|e|d|i|s|\b|m|o|n|g|o|d|b|\b|
假如我现在执行strcat(a,"666")操作如果忘记了给a分配新长度的话,内存就会溢出,从而影响b的值,而SDS避免了这个问题,当执行给SDS添加字符串会自动检查当前的free长度是否够用,如果不够会自动分配新空间,从而避免了内存溢出问题,其实说到这里其实SDS作为Redis存储的最细节关键的还是这个free缓冲,因为Redis的使用场景中大部分速度要求苛刻,且经常会发生字符串增加或者减少的事情,而如果每次都调用系统类库来分配内存空间,会很耗时,降低性能,而Redis考虑到了这一点,使用了free,大大减少了内存分配的次数,从而提高了性能。
3、C语言字符串不能用来存储二进制文件,因为c语言字符串利用了'\0'作为字符串结尾,但是二进制文件结尾是-1,而SDS有一个len变量,就解决了这个问题,可以包含多个'\0',从而可以存储任意二进制数据。
4、SDS也遵循了C语言字符串'\0'结尾的规则,使得SDS也可以使用一部分系统的类库。
区别图片