服务器一查内存:
$ free -h
total used free shared buff/cache available
Mem: 14Gi 10Gi 146Mi 0.0Ki 4.2Gi 4.1Gi
Swap: 0B 0B 0B
看到 free: 146Mi 就觉得”内存要爆了”——不对,Linux 从来不闲着,它会把空闲内存拿去做各种缓存。
各列到底是什么
| 列 | 含义 |
|---|---|
| total | 总内存 |
| used | 已被进程占用 |
| free | 完全空闲,谁都没在用(少不代表不好) |
| shared | tmpfs / shared memory 占用 |
| buff/cache | 内核用作 page cache / dentry 缓存 |
| available | 实际还能分配给程序的内存(这个才是真) |
关键:buff/cache 是弹性的——一旦有程序需要内存,内核会立刻回收 cache 让出来。所以真正衡量”还剩多少”的指标是 available,不是 free。
上面例子里 available = 4.1Gi,说明还能舒服再开 4G 内存的程序,没问题。
buff/cache 具体缓存什么
- Page cache:读过的文件内容缓存在内存里,下次读同一文件秒回
- Dentry cache:目录项缓存,让
ls/find之类操作更快 - Inode cache:文件元数据(大小、时间戳)缓存
- Buffers:块设备 IO 缓冲
这些都是性能加速——把内存”用起来”总比闲着好。
手动清 cache
极少用得上,但知道一下:
sync # 先把脏页刷盘
echo 3 > /proc/sys/vm/drop_caches # 清所有 cache
1= 清 page cache2= 清 dentry + inode3= 全清
清完 free -h 里 free 会瞬间变大——但系统 IO 性能会立刻下降,因为所有文件读要重新从磁盘拉。生产上除非做基准测试,不然不要清。
Swap = 0 的风险
上面的例子 Swap: 0B。开 swap 有一个好处:内存暂时不够时,把不活跃页面换到磁盘,避免 OOM Killer 杀进程。
没 swap 的情况,某个进程突然吃到 15G 内存,系统会直接触发 OOM Killer:
Killed process 12345 (python)
Killed process 23456 (mysqld)
杀谁看 oom_score(内核给每个进程算一个”该杀分数”),基本是”占内存多、优先级低”的先中招。
加个 swap(4G)
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
验证:
free -h
# Swap: 4.0Gi ...
开机自动挂载:
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
Swap 大小经验:
- 内存 < 2G:swap 是内存的 2 倍
- 内存 2-8G:swap 等于内存
- 内存 > 8G:swap 2-4G 或者干脆不开(数据库服务器)
找谁在吃内存
RSS 排序(真实占用物理内存):
ps aux --sort=-rss | head -20
或者 top 里按 M 排。列 RES才是实际占用,VIRT(虚拟内存)意义不大。
看某个进程详情:
cat /proc/<PID>/status | grep -E 'VmRSS|VmSize'
看具体是哪部分:
pmap -x <PID> | tail -1
MySQL / Redis / Java 类”吃内存大户”
这些程序的内存占用大多是配置定的:
- MySQL:
innodb_buffer_pool_size,默认可能占 70% 内存 - Redis:
maxmemory,不配就吃到爆 - Java:
-Xmx设堆大小,不设 JVM 会按机器算
上生产前把这些参数对着物理内存卡好,不然多进程叠加轻松超总内存。
Linux OOM 前的预警
看 dmesg 有没有:
sudo dmesg -T | grep -i "oom\|killed"
Out of memory: Killed process 12345 (python) total-vm:15234567kB
看到这个说明已经杀过了。生产上应该主动监控——node_exporter + Prometheus 采 node_memory_MemAvailable_bytes,跌破阈值发告警。
一句话总结
free -h 看的是 available,不是 free;buff/cache 是好东西不是问题。没 swap 的服务器建议加 4G 兜底,主要吃内存的程序(MySQL / Redis / Java)参数要卡死。
