Linux 内存不够了?free、top、vmstat 怎么看?
1. 前言
Linux 服务器内存不足时,常见现象包括:
- 服务响应变慢;
- 进程突然退出;
- 系统开始使用 Swap;
- OOM Killer 杀掉进程;
- SSH 登录变慢;
- Java、MySQL、Redis 等服务异常。
排查内存问题时,常用命令有:
free
top
vmstat
ps
smem
pmap
本文重点讲解 free、top、vmstat 的使用方法和判断思路。
2. Linux 内存不是越空越好
很多新手看到 free 中 free 很低,就以为内存不够了。
实际上 Linux 会尽量利用空闲内存做缓存,例如:
- page cache;
- buffer;
- 文件系统缓存。
这可以提升文件读取性能。
所以 Linux 中真正要关注的是:
available
而不是只看 free。
3. free 查看内存
执行:
free -h
输出示例:
total used free shared buff/cache available
Mem: 7.7G 3.2G 500M 100M 4.0G 4.1G
Swap: 2.0G 0B 2.0G
字段说明:
| 字段 | 含义 |
|---|---|
total |
总内存 |
used |
已使用内存 |
free |
完全空闲内存 |
buff/cache |
缓冲和缓存 |
available |
估算可用内存 |
Swap |
交换分区 |
判断内存是否紧张,重点看:
available
Swap 使用量
4. available 为什么重要
available 表示系统在不明显影响当前运行程序的情况下,还能提供给新进程使用的内存。
如果:
free 很低
buff/cache 很高
available 还很多
通常不是内存不足。
如果:
available 很低
Swap 开始增加
系统明显变慢
才更像内存压力问题。
5. top 查看进程内存
执行:
top
按:
M
按内存占用排序。
重点字段:
| 字段 | 含义 |
|---|---|
VIRT |
虚拟内存 |
RES |
实际物理内存 |
SHR |
共享内存 |
%MEM |
内存占比 |
排查时更关注:
RES
%MEM
因为 VIRT 可能很大,但不一定实际占用物理内存。
6. ps 查看内存最高进程
查看内存占用最高的前 10 个进程:
ps aux --sort=-%mem | head
输出示例:
USER PID %CPU %MEM VSZ RSS COMMAND
mysql 1234 10.0 35.0 ... mysqld
app 2345 80.0 25.0 ... java -jar app.jar
RSS 表示常驻物理内存,单位通常是 KB。
自定义输出:
ps -eo pid,ppid,user,%mem,rss,cmd --sort=-rss | head
7. vmstat 查看内存和系统状态
执行:
vmstat 1
每秒输出一次。
示例:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 0 512000 100000 4000000 0 0 1 2 100 200 10 5 80 5
重点字段:
| 字段 | 含义 |
|---|---|
free |
空闲内存 |
buff |
buffer |
cache |
cache |
si |
swap in,从 Swap 读入内存 |
so |
swap out,从内存写入 Swap |
r |
等待 CPU 的进程数 |
b |
不可中断睡眠进程数 |
判断内存压力重点看:
si
so
如果 si、so 长时间不为 0,说明系统正在频繁使用 Swap,内存压力较大。
8. Swap 是什么
Swap 是磁盘上的交换空间。
当物理内存不足时,系统会把部分内存页换出到 Swap。
查看:
free -h
swapon --show
Swap 可以防止系统立刻崩溃,但性能比内存慢很多。
频繁使用 Swap 会导致服务器明显变慢。
9. 判断是否内存不足
可以按下面标准判断:
| 现象 | 判断 |
|---|---|
| available 很低 | 内存紧张 |
| Swap 已使用很多 | 内存可能不足 |
| vmstat 中 si/so 持续不为 0 | 正在频繁换页 |
| OOM 日志出现 | 内存严重不足 |
| 某进程 RSS 持续增长 | 可能内存泄漏 |
| buff/cache 高但 available 也高 | 通常正常 |
10. 查看 OOM 记录
如果进程突然被杀,可以查 OOM:
dmesg | grep -i "killed process"
或:
journalctl -k | grep -i "killed process"
如果看到类似:
Out of memory: Killed process 1234 (java)
说明进程被 OOM Killer 杀掉。
11. Java 程序内存排查
Java 进程看起来内存大很常见。
需要区分:
- 堆内存;
- 非堆内存;
- 线程栈;
- 直接内存;
- Metaspace;
- JVM 自身开销。
查看 JVM 参数:
ps -ef | grep java
查看 GC:
jstat -gcutil PID 1000
查看堆直方图:
jmap -histo PID | head
生产环境执行 dump 要谨慎,因为可能造成停顿和磁盘占用。
12. MySQL 内存排查
MySQL 内存高可能和这些配置有关:
- innodb_buffer_pool_size;
- sort_buffer_size;
- join_buffer_size;
- max_connections;
- 临时表;
- 查询缓存。
查看进程:
ps aux --sort=-%mem | head
进入 MySQL:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW STATUS LIKE 'Threads_connected';
13. Redis 内存排查
Redis 是内存数据库。
查看 Redis 内存:
redis-cli info memory
关注:
used_memory_human
maxmemory
mem_fragmentation_ratio
如果没有设置 maxmemory,Redis 可能持续占用内存直到触发 OOM。
14. 临时释放缓存可以吗
可以执行:
sync
echo 3 | sudo tee /proc/sys/vm/drop_caches
但不建议把它当成常规解决方案。
缓存是 Linux 正常机制,释放缓存只能临时改变数字,不能解决根本问题。
真正要解决的是:
哪个进程占用内存
是否内存泄漏
是否配置不合理
是否需要扩容
15. 内存排查流程
free -h
top
ps aux --sort=-%mem | head
vmstat 1
swapon --show
dmesg | grep -i "killed process"
判断顺序:
看 available
↓
看 Swap 是否使用
↓
看 si/so 是否持续变化
↓
找内存最高进程
↓
结合应用类型继续分析
↓
查 OOM 日志
16. 小结
内存排查核心命令:
free -h
top
vmstat 1
ps aux --sort=-%mem | head
swapon --show
dmesg | grep -i "killed process"
关键判断:
不要只看 free
重点看 available
Swap 持续增长要警惕
vmstat si/so 持续不为 0 表示内存压力大
进程突然消失要查 OOM
Linux 内存排查的重点不是"空闲内存少",而是系统是否还有可用内存、是否频繁换页、是否有异常进程持续吃内存。