SDS(simple dynamic string): 简单动态字符串
SDS使用场景
- 包含字符串值的键值对,在底层都是由sds实现
- 用作缓冲区:AOF模块中的AOF缓冲区、客户端状态中的输入缓冲区
SDS定义
struct sdshdr {
// 记录buf数组中已使用字节的数量
// 等于sds所保存字符串的长度
unsigned char len;
// 记录buf分配的长度(除去了sds头和空’ ’结束符)
// 计算可用长度 avail = alloc - len
unsigned char alloc;
//只有3位有效位,因为类型的表示就是0到4,8位的flags有5位没有被用到
unsigned char flags;
// 字节数组,用于保存字符串,实际的字符串存在这里
// 最后一个字符保存空字符' '
char buf[];
};
空间预分配优化策略
// 若新的总长度小于1m,则分配新的总长度*2,否则分配新的总长度+1m
if (newlen < SDS_MAX_PREALLOC)
newlen *= 2;
else
newlen += SDS_MAX_PREALLOC;
惰性空间释放优化策略
当SDS的API需要缩短SDS保存的字符串时,程序并不立即使用内存重分配来回收缩
短后多出来的字节,而是使用free属性将这些字节的数量记起来,并等待将来使用
,
SDS与C字符串的区别
SDS | C字符串 |
---|---|
获取字符串长度复杂度O(1) 通过len属性实现 |
获取字符串长度复杂度O(N) |
杜绝缓冲区溢出 先检测空间大小再执行修改操作 |
可能造成缓冲区溢出 |
增长/缩短N次字符串最多进行N次内存重分配 通过alloc属性实现,实行空间预分配和惰性空间释放优化策略 |
增长/缩短N次字符串必定进行N次内存重分配 |
二进制安全 可以保存文本数据和任意格式的二进制数据 |
二进制不安全 只可以保存文本数据 |
可以使用部分<string.h>库的函数 | 可以使用所有<string.h>库的函数 |
源码阅读
- 文件:src/sds.h 、 src/sds.c
索引
redis 系列,要懂redis,首先得看懂sds(全网最细节的sds讲解)
Redis 字符串数据结构(String)底层存储源码分析