Redis 作为内存数据库,内存利用率直接影响成本和稳定性。很多人在面试中被问到“内存碎片率过高怎么办”时,只能答出 activedefrag yes,但实际排查和优化远不止一个开关。本文从原理到实战,帮你彻底理清思路。
一、什么是内存碎片率
Redis 的 INFO memory 中有一个关键指标:
mem_fragmentation_ratio: 1.8
计算公式:
mem_fragmentation_ratio = used_memory_rss / used_memory
used_memory:Redis 分配器统计的“逻辑内存”,即实际存储数据用掉的内存。used_memory_rss:操作系统看到的“物理内存”,即 Redis 进程占用的常驻内存。
理想情况下两者接近,比值在 1.0 ~ 1.5 之间属于正常。如果超过 1.5,说明碎片偏多;超过 2.0 则比较严重,意味着有大量内存被浪费。
反过来,如果比值 小于 1,说明部分内存被交换到磁盘(Swap),性能会急剧下降,这是另一个严重问题。
二、碎片是怎么产生的
要排查,先理解来源。Redis 默认使用 jemalloc 作为内存分配器,它按固定大小(如 8、16、32、48、64 字节等)分配内存块。碎片主要来自三个场景:
-
频繁的增删改
不断写入和删除不同大小的 key,释放的内存块无法被后续请求精确复用,形成“空洞”。 -
大量 key 过期或删除
集中过期会释放大量不连续的小块内存,分配器难以合并。 -
数据体积变化大
比如一个 List 从 1000 个元素缩到 10 个,底层内存不会立即归还操作系统。
简单说:分配器为了性能,不会频繁把内存还给操作系统,于是碎片就积累下来。
三、排查步骤
面试中如果被问“怎么排查”,要体现出结构化思路。
1. 确认碎片率真实水平
redis-cli info memory
重点看:
mem_fragmentation_ratioused_memory_humanused_memory_rss_humanallocator_frag_ratio(分配器内部碎片)allocator_frag_bytes
如果 allocator_frag_ratio 也很高,说明是分配器层面的碎片;如果它正常但总碎片率高,可能是操作系统或 Swap 导致。
2. 判断是否开启主动碎片整理
redis-cli config get activedefrag
如果为 no,说明 Redis 没有自动整理,碎片会持续累积。
3. 观察碎片增长趋势
redis-cli info memory | grep mem_fragmentation_ratio
隔一段时间多次执行,判断是稳定、缓慢增长还是突然飙升。突然飙升往往和一次大删除、大过期有关。
4. 检查是否发生 Swap
redis-cli info memory | grep mem_fragmentation_ratio
free -h
如果比值小于 1,且 free 显示 Swap 被使用,说明内存不足,需要优先扩容。
5. 检查大 key 和集中过期
redis-cli --bigkeys
redis-cli --scan --pattern '*' | head
大 key 删除、集中过期是碎片激增的常见诱因。
四、优化方案
根据排查结果,分层次处理。
方案一:开启主动碎片整理(activedefrag)
这是最直接的方案。Redis 4.0 引入,通过后台线程整理碎片。
redis-cli config set activedefrag yes
但要注意,它有几个阈值参数,默认值较保守:
redis-cli config set active-defrag-ignore-bytes 100mb
redis-cli config set active-defrag-threshold-lower 10
redis-cli config set active-defrag-threshold-upper 100
redis-cli config set active-defrag-cycle-min 5
redis-cli config set active-defrag-cycle-max 75
redis-cli config set active-defrag-max-scan-fields 1000
含义:
ignore-bytes:碎片小于 100MB 不整理。threshold-lower:碎片率超过 10% 才开始。threshold-upper:碎片率到 100% 时全力整理。cycle-min/max:整理占用的 CPU 时间比例。
建议:在业务低峰期开启,或调低 cycle-max 避免影响性能。开启后观察 active_defrag_running 指标。
方案二:重启实例
如果碎片率极高且无法在线整理,最彻底的方法是重启。重启后内存重新分配,碎片归零。
但重启有代价:
- 主从切换或集群迁移可减少停机。
- 需要确保 RDB/AOF 持久化正常,避免数据丢失。
生产环境优先用主从切换:先重启从节点,再故障转移,最后重启原主节点。
方案三:调整 maxmemory 和淘汰策略
如果内存接近上限,碎片会加剧。合理设置:
redis-cli config set maxmemory 8gb
redis-cli config set maxmemory-policy allkeys-lru
留出 20%~30% 余量,避免触发 Swap。
方案四:优化业务写入模式
- 避免大 key:把大 Hash、大 List 拆分成多个小 key。
- 打散过期时间:给 key 的 TTL 加随机值,避免集中过期。
- 控制数据体积:及时清理无用数据,使用
UNLINK替代DEL异步删除。
方案五:更换内存分配器
Redis 默认 jemalloc 已经比较优秀。如果使用 libc malloc,碎片可能更严重。可以在编译时指定:
make MALLOC=jemalloc
一般不建议在生产中随意更换。
五、面试答题模板
如果面试官问“Redis 内存碎片率过高怎么排查和优化”,可以这样组织:
- 定义:碎片率 = used_memory_rss / used_memory,正常 1.0~1.5。
- 排查:
INFO memory看比值、allocator_frag_ratio、是否 Swap、是否开启 activedefrag、是否有大 key 和集中过期。 - 优化:
- 开启
activedefrag,调整阈值和 CPU 占用。 - 低峰期重启或主从切换。
- 设置合理的
maxmemory和淘汰策略。 - 业务侧拆分大 key、打散过期时间。
- 开启
- 补充:比值小于 1 说明发生 Swap,优先扩容;整理碎片会消耗 CPU,需权衡。
六、总结
内存碎片率过高不是单一问题,而是分配器机制、业务写入模式和内存容量共同作用的结果。排查时先看指标,再定位原因,最后选择在线整理、重启或业务优化。开启 activedefrag 是最常用的手段,但它不是银弹——理解碎片来源,才能从根本上控制它。
在实际生产中,建议把 mem_fragmentation_ratio 纳入监控告警,超过 1.5 预警,超过 2.0 处理。这样既能保证 Redis 性能,也能避免内存浪费带来的成本上升。
未经允许不得转载:任鹏个人博客 » Redis 内存碎片率过高怎么排查和优化

