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

Redis String原理

一、Redis 字符串存储分为两层逻辑

层级说明举例
逻辑层(对象层)Redis 把字符串包装成一个 redisObject,这个对象有 typeencoding 字段type=string,encoding=int/embstr/raw
物理层(底层实现)实际的字符串数据由 SDS(Simple Dynamic String) 存储SDS 结构定义在 sds.h

也就是说:

String 类型的编码方式(int、embstr、raw)属于对象层;
SDS(sdshdr结构)属于物理层的存储结构。


二、Redis 3.2 前后 编码方式(type/encoding) 没有变化

三种编码方式在 Redis 5.0 前后是一致的:

encoding说明使用场景
int整数直接保存为 long longSET key 123
embstr字符串较短(≤ 44 字节),redisObject 和 SDS 一次性分配SET key "hello"
raw字符串较长(> 44 字节),redisObject 和 SDS 分开分配长字符串、大文本

🔸 Redis 3.2 没有改动这些编码方式的逻辑
它仍然会根据字符串的长度来判断使用 embstr 还是 raw


三、Redis 3.2 改动的其实是 SDS(Simple Dynamic String)结构实现

这一层属于 底层内存结构优化,不影响上层的 encoding 判定逻辑。

📜 Redis 3.2 之前的 SDS(单结构版)

早期版本使用固定结构:

struct sdshdr {int len;      // 已使用字节数int free;     // 剩余空间char buf[];   // 实际字符串
};

问题:

  • 所有字符串都要占用 8 字节元数据(两个 int)
  • 对于短字符串非常浪费内存(Redis 里很多 key 只有几字节)

📜 Redis 3.2 ~ 6.0 的 SDS(多结构分级优化)

Redis 引入了 多版本 SDS(sdshdr5/8/16/32/64)

struct sdshdr8 {//unit8_t固定宽度无符号整型,1字节,8表示位数uint8_t len;//len 存储的是 已使用的字节数uint8_t alloc;//alloc 存储的是 buf 数组总分配空间(包含已用 + 剩余空间)unsigned char flags;char buf[];
};

以及极致节省版:

struct sdshdr5 {unsigned char flags; // 高5位存len,低3位存类型char buf[];
};

1️⃣sdshdr5 为什么可以减少内存碎片化:

🔹内存碎片化来源

在动态内存分配中,碎片化主要有两种:

  1. 内部碎片(internal fragmentation)

    • 已分配的内存块中,有未使用空间
    • 例如:申请 2 字节,用了 16 字节内存 → 剩余 14 字节浪费
  2. 外部碎片(external fragmentation)

    • 多个小块散落在内存中,无法连续使用
    • 主要发生在大量不同大小对象频繁分配/释放时

在 Redis 里,大部分 key/value 是短字符串,如果用固定头部的 SDS(len+free = 8B):

  • 2B 字符串 → 占用 10B(2B 数据 + 8B 头)
  • 内部碎片占比 80%
  • 如果有上百万条短字符串,这些浪费累积起来非常可观 → 导致内存碎片化

2️⃣ sdshdr5 的优化方式

🔹 核心思路:

把头部压缩到 1 字节,只用于极短字符串(≤31B)

  • 高 5 位存 len,低 3 位存类型
  • buf[] 直接存储字符串
  • 总内存占用 = 头部 1B + 数据 1~31B
🔹 好处:
  1. 减少内部碎片

    • 短字符串的头部从 8B → 1B
    • 例如 "OK" 2B 数据,头部 1B → 总共 3B
    • 内部碎片从 8B → 1B,浪费内存大幅下降
  2. 增加连续分配空间

    • 内存占用小 → 相同内存页可以存放更多对象
    • Redis 对象多,连续存放更多对象 → 外部碎片减少
  3. 缓存友好

    • 头部 + 数据占用内存更小 → CPU 缓存命中率高
    • 频繁访问短字符串效率更高

3️⃣ 举例对比

字符串旧版 SDSsdshdr5说明
"OK" (2B)10B3B内部碎片减少 7B
"Hello" (5B)13B6B内部碎片减少 7B
"Redis" (5B)13B6B内存利用率提升 ~50%

对百万级短 key,总共可以节省几十 MB 到几百 MB 内存,碎片化明显下降。


这种设计根据字符串长度动态选择合适的结构,从而:

  • 小字符串用小结构(节省内存)
  • 大字符串用大结构(支持更长长度)

🔹 这是 Redis 3.2 前后最大的底层变化之一,但它属于 SDS 层,而非对象层。


四、总结对比

层级Redis 2.6 ~ 3.0Redis 3.2~是否变化
编码方式 (encoding)int / embstr / rawint / embstr / raw❌ 无变化
SDS 实现结构单一结构体(sdshdr)多层结构体(sdshdr5/8/16/32/64)✅ 有变化
影响内存利用率低小字符串节省内存✅ 优化效果显著

✅ 总结一句话

Redis 3.2 没有改变字符串的编码方式(int/embstr/raw)
重构了 SDS 动态字符串的实现结构 —— 从固定结构变为多级结构(sdshdr5/8/16/32/64),实现了更精细的内存优化。

http://www.dtcms.com/a/486310.html

相关文章:

  • 旅游网站功能流程图php wordpress教程
  • adminPage-vue3依赖LoadingWrap说明文档,表单页快速开发,使用思路及范例-汇总
  • 八股已死、场景当立(场景篇-JVM)
  • 【MySQL】主从复制
  • C4D域的常规修改层:功能详解与实用技巧
  • 网站后台管理系统模板仿西部数码网站
  • 外贸网站电子建设网站免费推广平台有哪些
  • 【汽车篇】AI深度学习在汽车轮胎X-ray缺陷检测应用方案
  • Jmeter循环控制器,IF控制器,正则表达式
  • 【qt学习】day1登录界面模仿
  • 一款优秀的桌面辅助软件
  • 2025-陇剑杯决赛-ezTraffic
  • 【Qt】1.安装QT
  • Spring AI 番外篇01:MCP Streamable HTTP 模式
  • 【GUI自动化测试】Python 自动化测试框架 pytest 全面指南:基础语法、核心特性(参数化 / Fixture)及项目实操
  • Vue3中组件间的数据传递【6】
  • nginx-1.16.1-2.p01.ky10.sw_64.rpm 安装教程(详细步骤,适用于Kylin V10/SW64架构)
  • 教育培训机构如何开发搭建自己的微信小程序?
  • 微软AutoGen:多智能体AI开发新利器
  • vscode的Verilog/SystemVerilog Tools(Andrew Nolte)插件简单配置
  • Rokid设备连接全解析:蓝牙与Wi-Fi通信源码深度剖析
  • 浦口区建设中学网站湖北什么是网站建设
  • 在阿贝云免费云服务器上体验LightGBM模型训练的愉快经历
  • 工业设计核心软件全解析:从绘图到高端制造
  • 20251015荣品的PRO-RK3566开发板在buildroot下解决驱动编译异常的问题
  • pytest 库用法示例:Python 测试框架的高效实践
  • 公司接到网站中文域名到期在云服务器打建网站
  • 为什么做的网站预览出来什么都没有wordpress开发西瓜
  • uniapp使用音频录音功能
  • 【Linux运维】 Prometheus + Grafana + Alertmanager 监控系统部署指南(CentOS Ubuntu 通用版)