FR Server Memory Leak / OOM: 6-Step Fix
发布时间:2026-10-15
问题一:服务器频繁 OOM 杀进程
- 表现:
dmesg | grep -i oom有大量 Out of memory 日志,进程(通常是 Java/PHP/MySQL)被内核杀掉。 - 可能原因:① 应用内存泄漏;② 内存配置超出物理内存;③ 突发流量导致并发连接暴涨。
- 排查步骤:
1.free -h看内存使用;
2.ps aux --sort=-%mem | head -10找吃内存的进程;
3. 看 OOM 日志确认被杀进程与当时内存。 - 快速修复:
1. 临时加 swap(16–32GB)应急;
2. 调小进程内存:Java-Xmx、PHPmemory_limit、MySQLinnodb_buffer_pool_size;
3. 重启释放内存。
问题二:Java 应用内存泄漏
- 表现:Java 进程内存持续增长,直到 OOM,重启后又慢慢涨。
- 可能原因:① 静态集合类未清理;② 未关闭的资源(流/连接);③ 缓存无上限。
- 排查步骤:
1.jstat -gc看 GC 情况;1s 10
2.jmap -heap看堆使用;
3.jmap -dump:live,format=b,file=heap.hprof导出堆分析。 - 快速修复:
1. 用 MAT/JProfiler 分析堆转储,找大对象/泄漏点;
2. 加内存上限-Xmx防止吃光系统内存;
3. 开启 GC 日志分析对象生命周期。
问题三:PHP-FPM 占满内存
- 表现:
ps aux | grep php-fpm显示大量进程,每个占几十 MB,总和打满内存。 - 可能原因:
pm.max_children设置过大,× 单进程内存 > 物理内存。 - 排查步骤:
1.ps aux | grep php-fpm | awk '{sum+=$6} END {print sum/1024 " MB"}看总内存;
2. 看pm.max_children配置。 - 快速修复:
1. 调小pm.max_children(建议 = 内存 / 单进程内存 × 0.7);
2. 设pm.max_requests = 500让进程定期重启释放内存;
3. 排查慢请求(可能是内存泄漏)。
问题四:MySQL 内存溢出
- 表现:MySQL 被 OOM kill,数据库重启后恢复。
- 可能原因:
innodb_buffer_pool_size过大,或连接数 ×sort_buffer_size超出内存。 - 排查步骤:
1. 计算 MySQL 最大内存 = buffer_pool + (连接数 × (sort_buffer + read_buffer + join_buffer));
2.SHOW VARIABLES LIKE 'innodb_buffer_pool_size';。 - 快速修复:
1. 调小innodb_buffer_pool_size(建议物理内存 50–70%);
2. 调小sort_buffer_size、read_buffer_size;
3. 限制max_connections。
问题五:Redis 内存打满
- 表现:
used_memory持续增长到maxmemory,写入报错或开始淘汰。 - 可能原因:① 缓存无过期时间;② key 设计不合理(大 key);③ maxmemory-policy 设为 noeviction。
- 排查步骤:
1.redis-cli info memory看内存;
2.redis-cli --bigkeys找大 key;
3.redis-cli config get maxmemory-policy。 - 快速修复:
1. 设maxmemory-policy allkeys-lru自动淘汰;
2. 给所有缓存 key 加 TTL;
3. 拆分大 key。
问题六:如何预防 OOM?
- 监控:内存使用率 >85% 告警,swap 使用 >0 告警。
- 资源限制:systemd 设
MemoryMax,防止单进程吃光内存。 - 合理配置:所有进程内存总和 ≤ 物理内存 70–80%,留余量给系统和突发。
- swap:保留 8–16GB swap 作为缓冲,不是替代内存。