一、先搞懂 3 个关键概念
- used:真正在用的内存
- buff/cache:系统缓存,可以回收,不算占用
- 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 种原因:
- 内存泄漏只涨不降,重启就好,过几天又爆
- 并发太高 / 流量突增瞬间把内存打满
- 堆设置太小(Java)-Xms -Xmx 不够
- 缓存 / 句柄 / 连接不释放连接池、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 频繁 = 堆不够或泄漏