news 2026/11/6 3:31:15

Redis 从 0 到 1(二十六):INFO memory 里 8 个关键数字——内存构成与容量规划

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis 从 0 到 1(二十六):INFO memory 里 8 个关键数字——内存构成与容量规划

我不会起名字322· 后端 / 算法 / 数据库

📘 技术栈 | 🧩 力扣 Hot100 | 🐹 Go 项目 | 🟥 Redis | 🐬 MySQL

文章目录

  • Redis 从 0 到 1(二十六):INFO memory 里 8 个关键数字——内存构成与容量规划
    • 一、现象:数据 1G,used_memory 2G
    • 二、INFO memory 的 8 个关键字段(收藏点 1)
    • 三、编码转换:同一份数据,内存差 5 倍
    • 四、Go 实操:编码转换的内存测量(收藏点 2)
    • 五、容量规划公式(收藏点 3)
    • 六、排查步骤:内存超标时按顺序看
    • 七、总结

Redis 从 0 到 1(二十六):INFO memory 里 8 个关键数字——内存构成与容量规划

上一篇《Redis 从 0 到 1(二十五):连接池又打满了——PoolSize 公式、泄漏排查与 PoolStats》我们把连接池调成了理性状态,链接:https://blog.csdn.net/2501_92769340/article/details/167399911 。
本篇往内存里看:Redis 的内存到底花在哪了,怎么规划才不被半夜的 OOM 叫醒。

一、现象:数据 1G,used_memory 2G

运维同学扩容前做容量核对:INFO memory显示 used_memory 2.1GB,而业务自己估算的数据量只有 1GB。“另一半被谁吃了?”

答案通常藏在四个口袋里:数据结构开销、编码差异、缓冲区、碎片。本篇把这四个口袋逐个拆开,给每个数字一个名字。

二、INFO memory 的 8 个关键字段(收藏点 1)

字段含义关注点
used_memoryRedis 自己记账的数据+结构总字节容量规划基准;admin 视角
used_memory_rss操作系统视角实际占用(含碎片、页缓存)与 used_memory 的比值见下行
mem_fragmentation_ratioRSS / used_memory1.0~1.1 健康;>1.5 警惕碎片(第 30 篇);<1.0 说明 swap 或共享内存
used_memory_dataset纯数据部分业务真实数据量
used_memory_overhead结构开销(dictEntry、redisObject、过期字典)overhead/dataset 比例反映 key 数量级开销
used_memory_luaLua 引擎占用(本系列不用 Lua,此项很小)异常增长要查
mem_clients_normal / mem_clients_slaves客户端输出缓冲slave 缓冲大 = 复制卡了(第 8 篇来源 3)
used_memory_startup启动基础开销常数,无需关注

经验诊断:

  • used_memory 涨但 used_memory_dataset 不涨→ 结构开销在涨:key 太多或大量空结构;
  • overhead 占一半以上→ key 设计有问题(短 key 千万级时 overhead 能超过数据本身,第 4 篇的 key 长度规范就是为它定的);
  • rss >> used_memory→ 碎片(下一篇)。

三、编码转换:同一份数据,内存差 5 倍

Redis 每种结构都有"紧凑编码"和"普通编码"两档,按元素数量/大小自动转换:

结构紧凑编码转换阈值(redis.conf 可调)普通编码
Hashlistpackhash-max-listpack-entries 128、hash-max-listpack-value 64hashtable
ZSetlistpackzset-max-listpack-entries 128skiplist
Listlistpacklist-max-listpack-size 128quicklist
Setintsetset-max-intset-entries 512hashtable

含义:一个 100 个 field 的小 Hash 走 listpack,内存接近纯数据;第 129 个 field 触发转换整体搬迁成 hashtable,内存瞬间翻几倍。同一份数据,128 个 field 和 129 个 field 的内存差可能是 3 倍——这就是"数据明明一样多,内存却对不上"的常见原因。

OBJECT ENCODING user:1001# 看当前编码CONFIG GET hash-max*# 看阈值

四、Go 实操:编码转换的内存测量(收藏点 2)

packagemainimport("context""fmt""time""redis-0to1/redisx")funcmain(){rdb,err:=redisx.NewClient(redisx.Config{Addr:"127.0.0.1:6379",Password:"redis123",PoolSize:10})iferr!=nil{panic(err)}ctx:=context.Background()// 对照实验:128 个 field(listpack)vs 200 个 field(hashtable),同 field 大小measure:=func(nint){key:=fmt.Sprintf("memtest:%d",n)pipe:=rdb.Pipeline()fori:=0;i<n;i++{pipe.HSet(ctx,key,fmt.Sprintf("f%03d",i),"value-of-same-length-32bytes")}pipe.Exec(ctx)enc,_:=rdb.ObjectEncoding(ctx,key).Result()usage,_:=rdb.MemoryUsage(ctx,key,0).Result()fmt.Printf("fields=%d 编码=%s 内存=%d 字节\n",n,enc,usage)rdb.Del(ctx,key)}measure(128)// 典型结果:编码=listpack,约 5KBmeasure(200)// 典型结果:编码=hashtable,约 15KB+(3 倍差)}

(数字随版本略有出入,量级不变:转换点前后内存差数倍。)

五、容量规划公式(收藏点 3)

实例容量规划: 1. 数据量 = 单条平均字节 × 条数 × 结构系数(listpack 小对象约 1.2,hashtable 约 2~4) 2. 加 key 开销:key 数 × (dictEntry+redisObject ≈ 100 字节) 3. 加缓冲区余量:AOF 重写缓冲区 + 复制缓冲 ≈ 数据量的 10%~20% 4. 加碎片余量:RSS = used_memory × 1.1~1.3(第 30 篇) 5. maxmemory 设为物理内存的 70%(给 fork 留出 COW 空间,第 7 篇 RDB 需要) 例:1 亿 key、单 value 500B、平均 3 个 field 的 Hash → 数据 50GB × 结构系数 2 + key 开销 10GB + 缓冲 12GB ≈ 122GB → 实例物理内存 ≥ 122GB / 0.7 ≈ 175GB → 一台装不下就上 Cluster 分片

六、排查步骤:内存超标时按顺序看

  1. INFO memory拍全景:dataset vs overhead vs rss 三分法定位大类;
  2. MEMORY USAGE抽查可疑大 key(第 22 篇);
  3. OBJECT ENCODING抽查高频 key 是否全在 hashtable(阈值被业务数据形态踩穿);
  4. 对照公式重算容量规划,决定扩内存还是拆 Cluster。

七、总结

  1. used_memory ≠ 数据量:结构开销、编码、缓冲、碎片四个口袋;
  2. 编码转换点(listpack→hashtable)是内存的隐形台阶,阈值可配可调可观测;
  3. 容量规划五步法:数据 × 结构系数 + key 开销 + 缓冲 + 碎片 + maxmemory 打 7 折;
  4. 小 Hash/小 ZSet 保持 listpack 是免费的内存优化。

下一篇预告:内存省了一半,网络传输还能再省——下一篇《JSON 体积是 Protobuf 的 3.7 倍?3 种序列化的 Go 基准测试》,用 Benchmark 数据说话,选对你的 Codec。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/6 3:30:48

Python aiearth-core 包详解与实战案例

1. 引言aiearth-core 是 AI Earth 平台推出的 Python 核心开发包&#xff0c;面向遥感影像处理、地理空间分析和 AI 模型应用场景&#xff0c;提供统一、简洁的编程接口。它把复杂的遥感数据获取、预处理、模型推理和结果可视化封装成易于调用的 API&#xff0c;帮助开发者快速…

作者头像 李华
网站建设 2026/11/6 3:24:16

UVa 780 Sentence Generator

摘要&#xff1a;本文讲解如何为 AND-OR\texttt{AND-OR}AND-OR 有向无环图实现增量句子生成器。核心思路是把 OR\texttt{OR}OR 节点的序列连接视为区间划分、把 AND\texttt{AND}AND 节点的笛卡尔积视为混合进制编码&#xff0c;通过预计算节点长度、OR\texttt{OR}OR 前缀和与 A…

作者头像 李华
网站建设 2026/11/6 3:18:14

FTM 精准时间测量技术

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/6 3:16:16

iloader iOS 侧载教程:免命令行,3 步在 iPhone 装好 SideStore

iloader iOS 侧载教程&#xff1a;免命令行&#xff0c;3 步在 iPhone 装好 SideStore 【免费下载链接】iloader User friendly sideloader 项目地址: https://gitcode.com/GitHub_Trending/iloa/iloader 免费 Apple ID 的证书配额用满、配对文件不知道丢进哪个目录、手…

作者头像 李华
网站建设 2026/11/6 3:06:22

ARM SCP电源管理深度解析:从SCMI协议到低功耗调试实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华