Redis 内存碎片率升高时怎么区分数据增长和分配器行为
来源:17golang原创
时间:2026-09-08 11:02:32 499浏览 收藏
Redis 的 mem_fragmentation_ratio 升高,并不等于当前数据量变大。先看 used_memory 与 used_memory_rss 的变化:前者跟着 Redis 当前分配的数据走,后者是进程驻留内存。删除过一批大键后,RSS 可能暂时留在高位;如果后续写入只复用了这些空闲块,RSS 不再上涨,原因更接近分配器行为,而不是数据持续增长。
- 先用
INFO memory建立两个时间点的内存基线,不要只盯碎片率。 - 用
SCAN分批遍历键名,再用MEMORY USAGE抽样定位业务前缀和大键。 - 删除后 RSS 不降可能是分配器保留页;只有逻辑占用和业务写入都持续上升,才更像数据增长。
先把 Redis 的四个内存指标放在一起看
排查从两个时间点开始:记录业务低峰和高峰,或记录处理一批删除动作前后的值。下面的命令只读取信息,不会扫描键空间:
redis-cli INFO memory | egrep 'used_memory:|used_memory_rss:|mem_fragmentation_ratio:|allocator_allocated:|maxmemory:' # 先保存逻辑占用、RSS、分配器和上限 redis-cli INFO stats | egrep 'instantaneous_ops_per_sec:|expired_keys:|evicted_keys:' # 同时记录写入压力和淘汰背景
可以把结果按这张表理解。used_memory_rss / used_memory 是碎片率的重要基础,但它不是“浪费空间百分比”,也不能跨分配器、版本和工作负载直接套一个硬阈值。
| 观察项 | 它回答什么 | 常见判断 |
|---|---|---|
used_memory | Redis 当前数据及内部分配用了多少 | 持续上升才支持“数据在增长” |
used_memory_rss | 进程实际驻留了多少内存页 | 删除后仍高,可能是分配器暂未归还 |
mem_fragmentation_ratio | RSS 与逻辑占用的关系 | 只能和时间序列及业务动作一起看 |
allocator_allocated | 分配器视角的已分配量 | 帮助区分 Redis 计数与分配器状态 |
例如删除大量缓存后,used_memory 下降、RSS 基本不动,随后新写入时 RSS 也保持平稳,这一组证据更符合“空闲块被复用”。反过来,两个指标都随键数量和写入量同步上升,才应优先查业务是否扩大了缓存范围、TTL 是否失效或 value 是否变大。

用 SCAN 和 MEMORY USAGE 找到真正变大的键
总量只能告诉你“哪里不对”,不能告诉你“谁变大了”。生产实例不要用 KEYS * 一次性阻塞遍历,而是用小批量 SCAN,配合 TYPE、MEMORY USAGE 和 TTL 做抽样:
redis-cli --scan --pattern 'session:*' | head -n 100 | while IFS= read -r key; do type=$(redis-cli TYPE "$key") # 先确认数据类型,避免按错结构处理 bytes=$(redis-cli MEMORY USAGE "$key" SAMPLES 5) # 用固定抽样近似单键占用,避免递归遍历全部元素 ttl=$(redis-cli TTL "$key") # 记录过期边界,判断增长是否来自长期不失效 printf '%s\t%s\t%s\t%s\n' "$bytes" "$ttl" "$type" "$key" done | sort -nr | head -n 20 # 先看抽样中的大键候选
这个示例只取前 100 个键,适合先确认命令和字段;正式排查应让游标完整走完,或按业务前缀分批运行并汇总。MEMORY USAGE 返回的是单键近似占用,SAMPLES 对嵌套类型影响精度;它适合排序和定位,不应被当作精确账单。
如果某个前缀的键数量明显增加,且大键候选没有变化,问题更可能是键数量或 TTL 变化;如果键数量稳定但少数 Hash、List、Set 或 ZSet 的占用持续上升,应检查集合是否没有上限、是否把过多字段塞进一个键,或是否误把明细数据放进缓存。

把碎片率、写入和删除时间对照起来
建议把每次采样保存成同一张表,而不是只在告警时看一次:
| 组合现象 | 更可能的原因 | 下一步 |
|---|---|---|
used_memory、RSS 都涨 | 数据量、value 或集合规模增长 | 按前缀和大键候选定位写入来源 |
used_memory 降、RSS 高位不动 | 删除后分配器保留已申请页面 | 观察后续写入是否复用 RSS,按峰值规划容量 |
| 键数量稳定、单键占用涨 | 集合字段或元素持续膨胀 | 检查写入边界、拆分结构和 TTL |
| 碎片率高但逻辑占用很低 | 历史峰值拉高了 RSS | 不要只按比例扩容,保留绝对值和时间序列 |
修复动作要跟证据匹配:数据真的增长时限制 TTL、控制集合大小或缩小缓存范围;只是 RSS 暂高时先观察分配器复用和峰值内存;单键膨胀时拆分结构或给写入设置上限。直接重启 Redis 可能让 RSS 下降,却会掩盖增长来源,也会引入持久化、故障切换和冷缓存成本。
常见问题
碎片率超过某个数值就必须重启吗?
不能只按一个数值决定。要同时看 used_memory、RSS、绝对内存余量、业务峰值和后续写入是否复用空闲块。
删除键后 RSS 为什么不马上下降?
底层分配器可能保留页面,供后续分配复用;这并不等同于 Redis 仍然持有同样的数据。容量规划应按历史峰值留余量。
MEMORY USAGE 能统计整个 Redis 的精确内存吗?
它用于查询单个键的近似占用,嵌套结构还会受 SAMPLES 影响。全局判断要结合 INFO memory 和分批扫描汇总。
参考资料
- Redis Memory optimization:RSS、分配器复用和碎片率的说明。
- Redis INFO:内存与运行统计字段。
- Redis SCAN、MEMORY USAGE:渐进遍历和单键占用查询。
-
288 收藏
-
423 收藏
-
377 收藏
-
154 收藏
-
501 收藏
-
104 收藏
-
114 收藏
-
数据库 · Redis | 10小时前 | 消息队列 · 消费组 · Redis Streams · 故障接管 · redis streams 消费组 XREADGROUP XACK XPENDING XAUTOCLAIM192 收藏
-
408 收藏
-
279 收藏
-
325 收藏
-
460 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习