Redis数据结构-SDS
1、Redis设计SDS的背景
优化C语言char* 字符数组的不足
操作效率低:获取长度需遍历,O(N)复杂度
二进制不安全:无法存储包含 \0 的数据(char* 数组用’\0’ 表述字符串结束 )
2、SDS数据结构
SDS 结构中记录了字符数组 使用的长度和分配的空间大小,避免了对字符串的遍历操作,可以直接获取到字符串的长度len,降低了操作开销 (空间换时间)
1 | struct __attribute__ ((__packed__)) sdshdr8 { |
- flags表示SDS的类型,一共有5种类型
sdshdr5(已废弃)、sdshdr8、sdshdr16、sdshdr32、sdshdr64, 区别:不同类型SDS结构中len和alloc这俩个元数据的数据类型不同(类型sdshdr8 表示 字符数组长度(包括最后一位0)不超过256字节(2^8) SDS设计不同的结构头(即不同类型),是为了能灵活保存不同大小的字符串,从而有效节省内存空间(因为保存不同大小的字符串时,结构头占用的内存空间也不一样,保存较小的字符串时,结构头也就占用较小的空间)
- attribute ((packed))的作用: 告诉编译器,在编译sdshdr8结构时,不要使用字节对齐的方式,而是**采用紧凑的方式分配内存-按实际占用的字节数,**来实现紧凑型内存布局,达到节省内存的目的
(字节对齐的方式: 这是因为在默认情况下,编译器会按照8字节对齐的方式,给变量分配内存。也就是说,即使一个变量的大小不到8个字节,编译器也会给它分配8个字节**)**
3、SDS的优势
操作效率高:获取长度无需遍历,O(1)复杂度
二进制安全:因单独记录长度字段,所以可存储包含 \0 的数据
兼容 C 字符串函数,可直接使用字符串 API
采用紧凑的方式分配内存
内存预分配:SDS 扩容,会多申请一些内存(小于 1MB 翻倍扩容,大于 1MB 按 1MB 扩容)
避免频繁的内存分配:SDS 缩容,不释放多余的内存,下次使用可直接复用这些内存 (这种策略,是以多占一些内存的方式,换取「追加」操作的速度,内存预分配策略,详细逻辑可以看 sds.c的 sdsMakeRoomFor 函数)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 ING-BLOG!
评论