🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
一,字符串 1.#### String的三种编码 * int,存储8个字节的长整型(long,2^63-1) * embstr,embstr格式的SDS(Simple Dynamic String) * raw,SDS,存储大于44个字节的字符串 2.String的三种编码转换 * 当 value 的值为整型时,编码为 int * 当 value 值为字符时,存储的编码为 embstr,连续的内存空间,只需要分配一次 * 当 value 值字符长度超过 44 时,存储的编码为 raw,不是连续的内存空间,需要分配两次 * 如果 value 的值为 int 或者 embstr ,然后通过 append 添加字符的时候,也会转化为 raw 类型(因为 embstr 设计的是只读的,如果发生变化只能再开辟一块空间),而且这个过程是不可逆的。 3.数据结构 ![](https://img.kancloud.cn/f8/ac/f8ac4543c410c7efdc4654de25ce3824_449x188.png) 3.**redis 为什么要自己写一个SDS的数据类型** ①、常数复杂度获取字符串长度   由于 len 属性的存在,我们获取 SDS 字符串的长度只需要读取 len 属性,时间复杂度为 O(1)。而对于 C 语言,获取字符串的长度通常是经过遍历计数来实现的,时间复杂度为 O(n)。通过 strlen key 命令可以获取 key 的字符串长度。   ②、杜绝缓冲区溢出   我们知道在 C 语言中使用 strcat 函数来进行两个字符串的拼接,一旦没有分配足够长度的内存空间,就会造成缓冲区溢出。而对于 SDS 数据类型,在进行字符修改的时候,会首先根据记录的 len 属性检查内存空间是否满足需求,如果不满足,会进行相应的空间扩展,然后在进行修改操作,所以不会出现缓冲区溢出。   ③、减少修改字符串的内存重新分配次数   C语言由于不记录字符串的长度,所以如果要修改字符串,必须要重新分配内存(先释放再申请),因为如果没有重新分配,字符串长度增大时会造成内存缓冲区溢出,字符串长度减小时会造成内存泄露。   而对于SDS,由于len属性和free属性的存在,对于修改字符串SDS实现了空间预分配和惰性空间释放两种策略:   1、空间预分配:对字符串进行空间扩展的时候,扩展的内存比实际需要的多,这样可以减少连续执行字符串增长操作所需的内存重分配次数。   2、惰性空间释放:对字符串进行缩短操作时,程序不立即使用内存重新分配来回收缩短后多余的字节,而是使用 free 属性将这些字节的数量记录下来,等待后续使用。(当然SDS也提供了相应的API,当我们有需要时,也可以手动释放这些未使用的空间。)   ④、二进制安全   因为C字符串以空字符作为字符串结束的标识,而对于一些二进制文件(如图片等),内容可能包括空字符串,因此C字符串无法正确存取;而所有 SDS 的API 都是以处理二进制的方式来处理 buf 里面的元素,并且 SDS 不是以空字符串来判断是否结束,而是以 len 属性表示的长度来判断字符串是否结束。   ⑤、兼容部分 C 字符串函数   虽然 SDS 是二进制安全的,但是一样遵从每个字符串都是以空字符串结尾的惯例,这样可以重用 C 语言库<string.h> 中的一部分函数。