当前位置: 首页 > news >正文

Redis数据结构-动态字符串

一、前言:为什么 Redis 要“再造”一个字符串?

Redis 是用 C 语言编写的,但却没有直接使用 C 语言的原生字符串(以\0结尾的char*)。这是为什么?

💡核心原因
C 字符串在性能、安全性和功能上,无法满足 Redis 作为高性能数据库的需求

为此,Redis 自研了一种名为SDS(Simple Dynamic String,简单动态字符串)的抽象类型,并将其作为 Redis 的默认字符串表示

本文将带你:

  • 拆解 SDS 的底层结构
  • 对比 SDS 与 C 字符串的 5 大差异
  • 揭秘 Redis 如何通过 SDS 实现 O(1) 长度获取、杜绝缓冲区溢出、高效内存管理

二、SDS 是什么?结构定义大揭秘

2.1 核心思想

SDS 在 C 字符串的基础上,增加了一个 header,用于存储元信息。

2.2 Redis 5.0+ 的 SDS 结构(优化版)

为了节省内存,Redis 针对不同长度的字符串,定义了5 种 header 结构

// 通用结构(概念模型) struct __attribute__ ((__packed__)) sdshdr { uint8_t flags; // 低3位表示类型,高5位未用 char buf[]; // 柔性数组,存放实际字符串 }; // 具体实现(根据字符串长度选择) struct __attribute__ ((__packed__)) sdshdr5 { unsigned char flags; // 3bit type + 5bit len (仅用于len<32) char buf[]; }; struct __attribute__ ((__packed__)) sdshdr8 { uint8_t len; // 已使用字节数 uint8_t alloc; // 总分配字节数(不含header和\0) unsigned char flags; char buf[]; }; struct __attribute__ ((__packed__)) sdshdr16 { uint16_t len; uint16_t alloc; ... }; struct __attribute__ ((__packed__)) sdshdr32 { uint32_t len; uint32_t alloc; ... }; struct __attribute__ ((__packed__)) sdshdr64 { uint64_t len; uint64_t alloc; ... };

关键字段说明

  • len字符串的实际长度(不包括结尾的\0
  • alloc已分配的总容量buf数组的大小 =alloc + 1,多出的 1 字节用于\0
  • flags:标识当前使用的是哪种 header(如sdshdr8

2.3 一个直观的例子

假设我们执行:

SET name "Redis"

Redis 会创建一个 SDS,其内存布局如下(以sdshdr8为例):

字段说明
len5"Redis" 长度为 5
alloc5初始分配 5 字节(无多余空间)
flags1表示使用sdshdr8类型
buf'R','e','d','i','s','\0'实际数据 + C 风格结尾

📌注意:SDS兼容 C 字符串,因此buf末尾依然保留\0,可以直接传给 C 库函数(如printf)。


三、SDS vs C 字符串:五大核心优势

特性C 字符串SDSSDS 的优势
1. 获取长度O(n)(需遍历到\0O(1)(直接读len性能飞跃,尤其对长字符串
2. 缓冲区安全易溢出(如strcat越界)自动检查并扩容杜绝安全漏洞
3. 内存重分配每次修改都可能realloc智能预分配/惰性释放减少系统调用,提升性能
4. 二进制安全不能包含\0(会被截断)可存储任意二进制数据支持图片、序列化对象等
5. 兼容性-兼容 C 字符串函数无缝集成现有生态

四、深度剖析:SDS 的三大内存优化策略

4.1 策略 1:空间预分配(sdsMakeRoomFor

当对 SDS 进行增长操作(如append)时,Redis 不仅分配所需空间,还会额外预分配

  • 若新长度 < 1MB:预分配等量的未使用空间
    (例:追加后 len=100 → alloc=200)
  • 若新长度 ≥ 1MB:预分配1MB的未使用空间

效果:N 次追加操作,最多触发 N 次内存重分配(通常远少于 N)。

4.2 策略 2:惰性空间释放(sdsRemoveFreeSpace

当对 SDS 进行缩短操作(如trim)时,Redis不立即释放内存,而是更新len,保留alloc

  • 好处:后续若再次增长,可直接使用预留空间,避免realloc
  • 手动释放:可通过sdsRemoveFreeSpaceAPI 强制释放。

4.3 策略 3:类型自适应(Header 优化)

  • 短字符串(< 32字节):用sdshdr5len/alloc字段,长度存于flags,极致省空间。
  • 长字符串:自动升级到sdshdr16/32/64,避免溢出。

效果:小 Key 场景下,内存占用比 C 字符串仅多 1~3 字节


五、SDS 在 Redis 中的应用场景

SDS 不仅是字符串值的载体,更是 Redis 内部的通用缓冲区

  1. 键(Key)和值(Value):所有字符串对象底层都是 SDS。
  2. AOF 缓冲区:写 AOF 文件前,命令先存入 SDS 缓冲区。
  3. 客户端输入缓冲区:存储客户端发来的命令。
  4. Lua 脚本:脚本内容以 SDS 形式存储。

一句话总结
SDS 是 Redis 内存世界的基石。”


六、动手实验:观察 SDS 的行为

6.1 查看字符串内部编码

# 创建一个字符串 > SET msg "Hello" OK # 查看底层编码(应为 embstr 或 raw,底层都是 SDS) > OBJECT ENCODING msg "embstr" # 追加内容,触发扩容 > APPEND msg ", World!" (integer) 13 # 再次查看(可能变为 raw) > OBJECT ENCODING msg "raw"

6.2 验证二进制安全

# 存储包含 \0 的二进制数据 > SET bin "\x00\xFF\x00" OK # 获取完整数据(长度为3) > GET bin "\x00\xff\x00" > STRLEN bin (integer) 3

C 字符串在此会返回长度 0


七、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

http://www.jsqmd.com/news/694142/

相关文章:

  • 嘉立创EDA:增加泪滴和铺铜以后,出现大量告警,通过重建所有铺铜来解决(包含内电层)
  • 2026年石笼网及相关产品厂家推荐:安平县铭邦金属丝网制造有限公司,石笼网兜、格宾石笼等全系供应 - 品牌推荐官
  • 网络安全薪资揭秘:小白如何逆袭30万年薪,必看收藏
  • VSCode+Python+遥感影像处理实战配置(农业AI工程师私藏版)
  • 2026年家用电梯厂家推荐:上海益到家科技有限公司,简易好安装好折叠电梯、座椅电梯等全系供应 - 品牌推荐官
  • 学术英语语境重构!英文论文降AI工具实测:如何从底层逻辑摆脱AIGC感?
  • LeetCode 118 杨辉三角 动态规划递推模型 C++二维数组题解
  • MySQL篇01-为什么MySQL默认引擎为Innodb
  • ModOrganizer2:游戏模组管理的革命性解决方案
  • 收藏!运维转网络安全完全指南:2026高薪转型路径+避坑攻略
  • 别再乱用if-else了!Verilog条件语句的5个实战避坑指南(附代码对比)
  • rules经验落盘
  • 2026年莫斯科清关代理及俄罗斯报关清关服务推荐:满洲里阿斯特兰纳国际供应链有限公司,提供全方位中俄清关服务 - 品牌推荐官
  • ChatGPT 5.5 重磅更新:从“会说话”到“会工作”
  • 日本“逝去的30年“:中年人最终学会了一件事——与自己和解
  • 终极指南:Windows Cleaner如何快速解决C盘爆红问题
  • 第4篇:Hermes记忆系统实战——让AI真正记住你
  • IMX890传感器在度信盒子上点不亮的排查实录:从MIPI速率到像素速率的完整调试思路
  • 【OpenClaw】通过 Nanobot 源码学习架构---(9)周期性执行
  • 2026年农村自建房墙改梁、老房墙改梁等施工服务推荐:南阳市卧龙区润固建筑修复加固工程队,经验丰富服务佳 - 品牌推荐官
  • XXMI启动器:一站式解决多游戏模组管理难题的智能平台
  • 信创环境实战:在麒麟Lylin v10 ARM服务器上离线部署Node.js生态
  • uniapp unipush推送调试实战:从通知消息到透传消息的完整避坑手册
  • B站成分检测器:如何快速识别评论区用户身份,提升互动效率
  • PyTorch模型加载翻车实录:遇到‘Missing keys’或‘Unexpected keys’报错怎么办?(附排查脚本)
  • 2026最权威的十大降重复率方案推荐榜单
  • 2026年螺旋丝杠保护套、钢制防护罩等机床防护产品厂家推荐:北京怡信康信测量设备有限公司,一站式满足多元设备需求 - 品牌推荐官
  • Windows上直接安装Android应用的终极指南:告别模拟器的5步快速方案
  • 5分钟快速上手:DLSS Swapper终极指南 - 免费提升游戏画质与性能的简单方法
  • 2026终极指南:如何轻松重置JetBrains IDE试用期,告别30天限制烦恼