我们知道Redis中最基础的类型就是字符串,但是Redis中的字符串与C语言中的常量字符串不相同,实际上是对C字符数组的封装,因为他需要支持动态扩张,支持值能够被修改,我们知道常量字符串是不能被修改的,read only,有点类似于C++中的std::string
.
127.0.0.1:6379> set name zhangsan
OK
上面指令中,在Redis中,底层分别是保存着name和zhangsan的SDS类型的对象或者实例。
127.0.0.1:6379> LPUSH num 1 2 3 4
(integer) 4
同样的,底层对应着的是num,1,2,3,4等五个字符串的SDS字符串对象实例。
定义
struct sdshdr
{
//当前字符串的长度,或者字符串数组已使用的容量
int len;
//数组中未使用字节的数量
int free;
//保存字符串的地方,以'\0'结尾
char buf[];
};
学过C++的同学有没有感觉就是用结构图封装了一个简单string,C++中的string底层是一个指针,也支持扩容修改等操作。
如图所示:
从这里就可以看出来,SDS记录了字符串的长度,那么我们获取字符串长度是O(1)的,在C语言中,我们获取字符串长度是O(n)的,因为需要一直遍历到’\0’为止。
127.0.0.1:6379> STRLEN name
(integer) 8
API
也提供了一些给类型的一些操作,比如字符串的拷贝,连接,截取等,但是都比较安全的。
比如字符串的拼接,拼接前会进行查看当前剩余的空间够不够保存的,不够的会进行底层字符数组重分配,当然他可能会进行空间的预分配,为了提高效率,减少系统调用的发生。但是C语言不会进行检查,所以可能会发生内存越界等崩溃bug.
对于内存的回收,使用的是“惰性空间释放”,也就是不是直接将内存归还操作系统,而是移动free的位置即可,当然真正需要释放的时候,他会真正的将资源归还给操作系统,它提供了这样的接口。
二进制安全
C字符串
C字符串只能用于存放文本数据,对于图片,视频等二进制数据不能很好的支持,因为C字符串只能在末尾包含空的字符串,如果在中间包含,可能导致一些数据被丢失。
SDS
底层是一个数组,无所谓空的字符串,怎么存入,获取的时候怎么返回即可,所以能很好的支持二进制类型数据的存放。