Back to Knowledge Hub

    Redis 的 SDS 是什么?跟传统 C 字符串相比有什么优势?

    Redis
    数据结构
    SDS
    字符串优化

    什么是 SDS?

    SDS(Simple Dynamic String)是 Redis 自主研发的字符串结构,专为高性能场景设计。作为 Redis 最基础的数据结构,它支撑着所有键值存储、列表元素等核心功能,其设计哲学可用三个关键词概括:安全高效灵活

    SDS 的底层结构

    SDS 结构示意图

    每个 SDS 包含三个关键元信息:

    1. 长度标识(len):实时记录字符串当前长度(8字节)
    2. 空闲空间(free):预分配未使用的缓冲区大小(8字节)
    3. 字符数组(buf):实际存储内容的柔性数组

    这种设计使得 SDS 在内存布局上形成三段式结构:头部元数据 + 数据区 + 预留空间。以存储 "Hello" 字符串为例:

    len=5          ← 当前字符串长度
    free=3         ← 剩余可用空间
    buf=['H','e','l','l','o','\0','',''] ← 实际存储(包含结尾空字符和预留空间)
    

    核心优势

    1. 快速长度获取

    传统 C 字符串需要遍历整个字符数组才能得到长度(时间复杂度 O(n)),而 SDS 直接读取 len 属性(O(1))。在访问 LIST 等数据结构时,这种优化可使性能提升 100 倍以上。

    2. 防止缓冲区溢出

    SDS 的空间预分配策略彻底解决了 C 字符串的溢出风险:

    • 当字符串长度 < 1MB 时:扩容后预留 100% 空闲空间(翻倍扩容)
    • 当长度 ≥ 1MB 时:每次扩容额外预留 1MB 空间

    这种机制使得 Redis 在处理 APPEND 等操作时,内存重分配次数减少 50% 以上。

    3. 二进制安全

    SDS 允许存储任意二进制数据(包括含 '\0' 的内容),这个特性使得 Redis 可以安全存储:

    • 图片的二进制数据
    • 序列化的 Protobuf 消息
    • PDF 文件片段

    而 C 字符串会因遇到 '\0' 提前截断,导致数据损坏。

    4. 兼容 C 字符串

    虽然 SDS 在功能上全面超越 C 字符串,但仍然保留以 '\0' 结尾的特性。这使得 SDS 可以:

    • 直接使用 C 语言的字符串函数库
    • 与现有系统 API 无缝对接
    • 降低开发者的学习成本

    5. 内存优化策略

    通过惰性空间释放机制,SDS 在缩短字符串时不会立即回收内存,而是将多余空间计入 free 字段。当下次需要扩容时,可直接复用这些空间,将内存分配次数降低 30%-50%。

    6. 类型分级

    Redis 为不同长度的字符串设计了 5 种 SDS 类型(sdshdr5~sdshdr64),通过元数据头的差异化设计,最小化内存开销:

    类型长度范围元数据头大小
    sdshdr50-31字节1字节
    sdshdr832-255字节3字节
    sdshdr16256-65535字节5字节
    sdshdr3265536-4294967295字节9字节
    sdshdr64超长字符串17字节

    SDS 在 Redis 中的应用

    1. 键值存储:所有 Redis 键都是 SDS 类型
    2. 列表元素:LIST 结构的元素存储依赖 SDS
    3. 持久化缓冲:AOF/RDB 文件写入使用 SDS 作为缓冲区
    4. 网络协议:RESP 协议解析基于 SDS 实现

    相关推荐: