动态字符串SDS
我们都知道redis的key是字符串,value往往也是字符串或字符串的集合。可见字符串是一种很常见的数据数据结构
不过redis并没有用c语言的字符串,因为c语言字符串存在很多问题
- 获取字符串长度需要运算
- 非二进制安全(从指针起始位置开始读取,直到结束符)
- 不可修改
所以reids没有采用c语言的字符换,而是采用了SDS动态字符串
其中
- len是保存的字符串字节数,8位,直接可以访问len来获取字符串长度
- alloc保存的是申请的内存总字节数, 8位
- flag表示不同的头类型,因为sds有很多,有最大8位, 32位, 64位(为了节约内存redis进行的设计,因为有些字符串很小,len和alloc没必要用很大位的数据结构进行存储,采用位数小的可以节约内存)
- buf便是真正存储的字符串
例如:有个字符串‘name’,他的SDS的数据结构如下
len为4,但是字符串后有个结束标识,读取字符串的时候,len位4,读取字符串从开始一直读取到结束,不管中间是否有结束符,这样就保证了二进制是安全的。如果想获取字符串长度,直接读取len
另外SDS也是支持动态扩容的:
例如:我有个字符串’hi’,要在’hi’后增加一个’,marry’
这里会重新申请内存空间
- 如果新字符串小于1M,则重新申请的空间为扩展后字符串长度2倍+1
- 如果新字符串长度大于1M,则重新申请的空间为字符串长度 + 1M + 1, 称为内存预分配(减少内存的分配次数)
那么扩容结束后如下
总结SDS:
优点
- 获取字符串长度时间复杂度为O(1)
- 支持动态扩容
- 减少内存分配次数
- 二进制安全的