Redis的字符串是如何实现的
Redis的字符串是如何实现的 收藏 本篇文章给大家分享《Redis的字符串是如何实现的》,覆盖了数据库的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。 在Redis这种内存数据库中,由于字符串被广泛的应用,在设计字符串时基于以下几点来设计: 1.支持丰富高效的字符串操作,比如追加、拷贝、比较等操作 2.能保存二进制数据 3.能尽可能的节省内存开销 可能会有人问了,既然C语言库提供了char*这样的字符数组来字符串操作。比如strcmp,strcat。感觉完全可以考虑直接使用C库提供的啊。C库字符串运用是很普遍,但是也不是没有问题的。它需要频繁的创建和检查空间,这在实际项目中其实很花时间的。所以,Redis设计了简单字符串(SDS,Simple Data )来表示字符串。同原来的C语言相比提升了字符串的操作效率,而且还支持二进制格式。下面我们就来介绍下Redis的字符串是如何实现的。 为什么不用char* 先来看看char*字符数组的结构,其实很简单就是开辟一块连续的内存空间来依次存放每一个字符,最后一个字符是”\0″表示字符串结束。C库中的字符串操作函数就是通过检查”\0″来判断字符串结束。比如strlen函数就是遍历字符数组中的每一个字符并计数,直到遇到”\0″结束计数,然后返回计数结果。下面我们通过一个代码来看看”\0″结束字符对字符串长度的影响。 这段代码的执行结果如下: 表示a1的字符长度是2个字符。这是因为在he后面有了”\0″,所以字符串以”\0″表示结束,这就会产生一个问题,如果字符串内部本身就有”\0″,那么数据就会被”\0″截断,而这就不能保存任意二进制数据了。 传统设计操作复杂度高 除了上面提到的不能保存任意二进制数据以外,操作复杂度也挺大。比如C语言中用得比较普遍的strlen函数,它要遍历字符数组中的每一个字符才能得到字符串长度。所以,时间复杂度是O(n)。另外再说一个常用函数strcat,它同strlen函数一样先遍历字符串才能得到目标字符串的末尾,而且它把源字符串追加到目标字符串末尾的时,还得确认目标字符串是否具有足够的空间。所以在调用的时候,开发人员还要人为保证目标字符串有足够的可用空间,不然就需要动态地申请空间。这样不仅时间复杂度高,操作复杂度也高了。 SDS的设计 Redis在设计的时候还是尽量保证复用C标准的字符串操作函数的。Redis在保留了使用字符数组来保存实际数据基础上,专门设计了一种SDS数据结构。 首先,SDS结构里面包含了一个字符数组buf[],同时SDS结构里面还包含了三个元数据。分别是字符数组现有长度len,分配给字符数组的空间长度alloc以及SDS类型flags。其中len和alloc这两个元数据定义了不同类型的SDS。SDS定义代码如下所示: typedef char *sds; /* Note: sdshdr5 is never…