内存占用高与 OOM 排查

一、先搞懂 3 个关键概念

  1. used:真正在用的内存
  2. buff/cache:系统缓存,可以回收,不算占用
  3. available:真正还能给应用用的内存

看内存只看这一条:

bash

free -h

重点:

  • available 快没了 → 内存真不够
  • 光 used 高、但 available 充足 → 没事

二、什么是 OOM?

  • Out Of Memory
  • 内存耗尽,系统自动杀进程保服务器不死
  • 一杀就掉服务,线上最恐怖问题之一

怎么确认是不是 OOM 了?

bash

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

bash

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

看到类似:

Out of memory: Kill process 1234 (java)

就是被系统 OOM 杀掉了

三、内存占用高 排查步骤(万能流程)

1. 看整体内存

bash

free -h

2. 看谁吃内存最多

bash

top

M 按内存排序

3. 看进程详细内存

bash

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

4. 看内存用在哪(VSZ / RSS)

  • VSZ:虚拟内存(不用太在意)
  • RSS实际物理内存(重点)

四、OOM 排查完整流程(最关键)

1. 确认 OOM 发生

bash

dmesg -T | grep -i "oom"

2. 看谁被杀死

日志里会有:

  • pid
  • 进程名(java、nginx、node 等)
  • 占用内存大小

3. 看为什么内存爆了

常见 4 种原因:

  1. 内存泄漏只涨不降,重启就好,过几天又爆
  2. 并发太高 / 流量突增瞬间把内存打满
  3. 堆设置太小(Java)-Xms -Xmx 不够
  4. 缓存 / 句柄 / 连接不释放连接池、Redis、文件句柄泄漏

五、Java 内存爆 & OOM 专用排查(运维最常用)

1. 看 Java 进程

bash

ps aux | grep java

2. 看堆内存使用

bash

jstat -gc  PID  1000

重点看:

  • O:老年代
  • FGC:Full GC 次数FGC 越来越多、回收不掉 → 内存泄漏

3. 导出堆 dump(定位泄漏代码)

bash

jmap -dump:format=b,file=heap.hprof PID

下载下来用:

  • MAT
  • JProfiler分析谁占了大量对象。

六、Linux 系统层面防 OOM 技巧

1. 调整 OOM 优先级(不杀重要进程)

值越小,越不容易被杀:

bash

echo -1000 > /proc/[PID]/oom_score_adj

2. 配置 SWAP(应急用)

bash

# 创建swap
dd if=/dev/zero of=/swapfile bs=1G count=2
mkswap /swapfile
swapon /swapfile

3. 限制进程内存

用 systemd 或容器限制内存,防止拖死整机。

七、你直接背的万能口诀

  • free -h 看 available
  • top + M 找内存大户
  • dmesg 查 OOM
  • jstat 看 GC
  • jmap 抓堆 dump
  • 只涨不降 = 泄漏
  • 突涨 = 流量 / 并发高
  • FGC 频繁 = 堆不够或泄漏
滚动至顶部