服务器经常内存莫名其妙占满、负载飙升、应用被系统杀死、甚至整机自动重启,这是线上最典型、也最让人头疼的故障之一。 很多人遇到只会重启服务器,治标不治本,过几天又复发。

我最近在河南一家知名IDC公司郑州易方科贸(861.cn)碰到过种问题,我将给出完整、可落地、从定位到根治的排查方案,新手也能一步步照着做。


一、先搞懂:什么是 OOM?为什么会自动重启?

OOM = Out Of Memory(内存溢出)。

当 Linux 系统物理内存 + Swap 都耗尽时,内核会启动 OOM Killer 机制,强制杀掉占用内存最高的进程,保护系统不彻底卡死。

  • 被杀的通常是:Java、PHP-FPM、Nginx、MySQL、Python 等应用
  • 严重时系统直接崩溃、自动重启

只要出现 OOM,说明内存资源已经彻底不够用或严重泄漏


二、第一步:快速确认是不是 OOM 导致重启

先判断故障根因,不要盲目优化。

1. 查看系统 OOM 日志

bash

运行

dmesg | grep -i "out of memory"
dmesg | grep -i oom

如果出现类似内容:

plaintext

Out of memory: Kill process 1234 (java)

说明就是 OOM 杀死了进程。

2. 查看系统日志(更完整)

bash

运行

grep -i "oom" /var/log/messages
grep -i "oom" /var/log/syslog

能看到:

  • 什么时候触发 OOM
  • 哪个进程被杀死
  • 当时内存占用情况

3. 看当前内存状态

bash

运行

free -h

重点看:

  • used 接近总内存
  • swap 被占满 基本就是内存溢出环境。

三、第二步:定位谁在吃内存?

1. 实时看内存占用最高的进程

bash

运行

top

M 键(大写),按内存排序。

重点关注:

  • Java 进程
  • MySQL
  • PHP-FPM 子进程过多
  • Nginx
  • Python/NodeJS 应用
  • 定时任务、爬虫、导入导出脚本

2. 更直观的内存排行

bash

运行

ps aux --sort=-%mem | head -10

直接列出内存占用前 10 进程,一眼找到元凶。


四、第三步:内存飙升的 5 大真实原因

1. 内存泄漏(最常见)

应用没有正确释放内存,越跑占得越多。 典型:

  • Java 内存泄漏
  • Go/Python 长驻进程缓存失控
  • 连接池不释放
  • 本地缓存无过期策略

表现:

  • 内存缓慢上涨,几天必爆
  • 重启后恢复,之后继续涨

2. 进程数量爆炸

PHP-FPM、Nginx、uWSGI 等子进程疯狂被拉起,导致总内存爆掉。

bash

运行

ps aux | grep php-fpm | wc -l
ps aux | grep nginx | wc -l

几百上千个进程,内存直接被吃光。

3. 一次性大任务压垮内存

一次性加载大量数据到内存:

  • 大数据导入导出
  • 大文件读取
  • 全表查询不加 limit
  • 报表统计、批量计算

瞬间把内存打满,直接 OOM。

4. 日志 / 缓存占满 Buff/Cache

Linux 会把空闲内存用作文件缓存,看起来内存很高,但正常情况下不会触发 OOM。 如果 Buff/Cache 异常巨大,可能是:

  • 大量小文件读写
  • 日志疯狂输出
  • 磁盘 IO 异常

可以手动释放:

bash

运行

sync && echo 3 > /proc/sys/vm/drop_caches

但这只是临时缓解。

5. Swap 配置不当或没有 Swap

没有 Swap → 内存一满直接 OOM Swap 太小 → 高并发下依然顶不住


五、第四步:从临时应急到彻底解决

(1)应急处理(快速恢复)

  1. 杀死异常占用内存的进程

bash

运行

kill -9 进程PID
  1. 重启异常服务
  2. 增加 Swap(临时救命)

bash

运行

fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
  1. 限制突发大流量、暂停批量任务

注意:应急只是恢复业务,不是根治。


(2)根治方案:从应用到系统

1. 应用层限制内存(最有效)
  • Java:设置 Xmx 最大堆内存

plaintext

-Xmx2G -Xms2G
  • PHP-FPM:限制最大子进程数、请求回收次数
  • NodeJS/Python:控制并发、限制内存缓存
2. 修复内存泄漏
  • 检查代码:连接未关闭、缓存未清理、死循环
  • 检查第三方库、中间件版本 bug
  • 开启应用内存监控
3. 控制进程数量

以 PHP-FPM 为例:

plaintext

pm.max_children = 50
pm.process_idle_timeout = 10s

避免进程无限创建。

4. 优化大查询、大任务
  • SQL 加 limit,避免全表加载
  • 大文件分块读取
  • 耗时任务异步化、队列化
  • 大数据导出走临时文件,不加载内存
5. 系统层优化
  • 配置合理 Swap(一般等于内存或 1/2)
  • 设置内存水位线告警
  • 开启日志轮转,避免日志疯长
  • 必要时升级服务器内存配置

六、第五步:预防监控,避免再次发生

  1. 配置内存使用率告警(超过 85% 告警)
  2. 监控 Swap 使用情况
  3. 监控进程数量、应用堆内存
  4. 定时清理日志、缓存
  5. 关键服务设置自动重启、自我保护
  6. 高并发业务做集群、负载均衡

七、一句话排查流程

  1. 看 OOM 日志 → 确认是内存溢出
  2. top/ps 找占用内存最高的进程
  3. 判断是泄漏、进程过多、还是大任务导致
  4. 临时杀进程 / 加 Swap 恢复业务
  5. 从应用配置、代码、系统层面彻底优化
  6. 加监控,防止复发
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐