Redis 的 SDS 和 C 中字符串相比有什么优势?
Redis 的 SDS 和 C 中字符串相比有什么优势?
C 语言使用了一个长度为 N+1
的字符数组来表示长度为 N
的字符串,并且字符数组最后一个元素总是 \0
,这种简单的字符串表示方式 不符合 Redis 对字符串在安全性、效率以及功能方面的要求。
C语言的字符串可能有什么问题?
这样简单的数据结构可能会造成以下一些问题:
- 获取字符串长度复杂度高 :因为 C 不保存数组的长度,每次都需要遍历一遍整个数组,时间复杂度为O(n);
- 不能杜绝 缓冲区溢出/内存泄漏 的问题 : C字符串不记录自身长度带来的另外一个问题是容易造成缓存区溢出(buffer overflow),例如在字符串拼接的时候,新的
- C 字符串 只能保存文本数据 → 因为 C 语言中的字符串必须符合某种编码(比如 ASCII),例如中间出现的
'\0'
可能会被判定为提前结束的字符串而识别不了;
Redis如何解决?优势?
简单来说一下 Redis 如何解决的:
- 多增加 len 表示当前字符串的长度:这样就可以直接获取长度了,复杂度 O(1);
- 自动扩展空间:当 SDS 需要对字符串进行修改时,首先借助于
len
和alloc
检查空间是否满足修改所需的要求,如果空间不够的话,SDS 会自动扩展空间,避免了像 C 字符串操作中的溢出情况; - 有效降低内存分配次数:C 字符串在涉及增加或者清除操作时会改变底层数组的大小造成重新分配,SDS 使用了 空间预分配 和 惰性空间释放 机制,简单理解就是每次在扩展时是成倍的多分配的,在缩容是也是先留着并不正式归还给 OS;
- 二进制安全:C 语言字符串只能保存
ascii
码,对于图片、音频等信息无法保存,SDS 是二进制安全的,写入什么读取就是什么,不做任何过滤和限制;