做运维 18 年,见过太多人被 free -h 的输出误导。收到业务卡顿告警登录机器,第一指令敲 free,一眼看到剩余内存尚可,下意识排除内存问题,转头去排查 CPU、磁盘 IO,兜兜转转耗费大量时间,最后才发现病根依旧在内存。
这类故障有很强迷惑性:不会直接触发进程 OOM 杀死服务,而是持续性抖动、间歇性卡顿,时好时坏,难以稳定复现,非常容易被归为网络、业务代码问题。
一、先理清最核心误区:buff/cache 不等于可直接使用内存
先回顾 free 输出关键字段,很多人认知停留在几年前的旧思想。
bash
c
free -h
- total:总物理内存
- used:已占用内存
- free:彻底空闲、没有任何数据的裸内存
- available:重点!应用程序真正能够申请到的内存
很多运维只看 free 列。Linux 内核会尽可能利用空闲内存用作 PageCache、Buffer,加速文件读写。这部分缓存可以回收,但回收存在成本,不是瞬间完成。当系统持续大量申请内存,内核需要频繁回收页面,如果回收速度跟不上应用分配速度,业务进程就会短暂阻塞,直观感受就是服务器卡顿。
关键结论:判断内存是否紧张,优先看
available,不要盯着 free。
二、造成 "内存看着空闲,机器持续卡顿" 四类典型场景
场景 1:available 持续走低,内核频繁回收页缓存
free 数值很大,但 available 持续偏低。新业务申请内存时,内核需要同步回收大量 pagecache,产生 CPU 开销、IO 抖动,引发业务短暂停滞。
场景 2:Swap 频繁读写(最常见)
物理内存尚有剩余,但系统一直在使用 Swap。常见诱因:swappiness 参数配置不合理;存在大量长期闲置内存,内核主动换出至 Swap。一旦进程需要重新访问这部分内存,触发磁盘 IO,延迟瞬间拉满。
bash
bash
# 观察Swap交换波动
vmstat 1
si(换入)、so(换出)持续大于 0,就是危险信号。
场景 3:内存碎片严重
长期运行的服务器,频繁创建销毁进程、大量 mmap 操作,造成物理内存碎片化。系统拥有足够总空闲内存,却没有连续大块内存可供分配。应用申请大内存时分配失败、发生阻塞,严重时直接触发 OOM。
bash
bash
# 查看内存碎片
cat /proc/buddyinfo
场景 4:透明大页 (THP) 引发系统卡顿
数据库、中间件服务器重灾区。开启透明大页后,内核异步整理大页内存,高峰期引发莫名延迟,内存指标看上去一切正常。
三、线上标准化排查流程
-
free -h优先观测 available,确认真实可用内存水位; -
vmstat 1观察 si/so,定位是否存在 Swap 交换; -
查看
/proc/meminfo,重点关注:- MemAvailable
- SwapTotal、SwapFree
- PageTables、Slab 占用
-
sar -B 1观测页面回收、缺页异常指标; -
检查透明大页配置:
cat /sys/kernel/mm/transparent_hugepage/enabled -
dmesg检索内核页面回收、内存相关日志,查看有无内核告警。
四、落地优化方案
- 观测指标切换基准所有监控告警抛弃 free,以 MemAvailable 作为内存水位判断依据。
- 合理调整 swappiness业务服务器推荐设置 10,减少内核主动将内存换入 Swap:
bash
ini
sysctl vm.swappiness=10
- 数据库、中间件关闭透明大页 THP
bash
typescript
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
- 规范应用内存配置Java 程序 Xmx 不要设置接近整机内存,预留系统与缓存工作内存,避免把可用内存压榨殆尽。
不建议频繁执行
echo 3 > /proc/sys/vm/drop_caches。临时释放缓存治标不治本,频繁操作反而加剧 IO 波动,只能应急,不能常态化使用。
五、可用巡检脚本(生产直接部署)
脚本功能:监控 MemAvailable 水位、Swap 交换指标,异常输出告警信息。
bash
bash
#!/bin/bash
WARN_RATIO=20
MEMINFO=$(cat /proc/meminfo)
AVAIL=$(echo "$MEMINFO" | grep MemAvailable | awk '{print $2}')
TOTAL=$(echo "$MEMINFO" | grep MemTotal | awk '{print $2}')
RATIO=$(( $AVAIL * 100 / $TOTAL ))
# 判断可用内存占比
if [ $RATIO -lt $WARN_RATIO ];then
echo "【内存预警】可用内存占比低于${WARN_RATIO}% ,当前比例:${RATIO}%"
fi
# 检测Swap活动
VMSTAT=$(vmstat 1 1 | tail -n1)
SI=$(echo $VMSTAT | awk '{print $7}')
SO=$(echo $VMSTAT | awk '{print $8}')
if [ $SI -gt 0 ] || [ $SO -gt 0 ];then
echo "【内存预警】系统正在频繁进行Swap交换!si:$SI so:$SO"
fi
可配合 crontab 定时执行,对接告警平台。
六、标准化 SOP 与 AIOps 预防思路
- 故障初次出现:收集 meminfo、vmstat、进程内存快照,临时优化缓解;
- 故障复现:纳入优化清单,调整 swappiness、关闭 THP、优化应用内存参数;
- 监控层面:除固定阈值告警,新增available 持续缓慢下降趋势告警,提前捕捉内存缓慢消耗隐患;
- AIOps 轻量化思路:定时自动采集内存关键指标,长期绘制基线,区分正常波动与异常内存回收行为。
运维总结
很多运维排查有固定惯性:先看 used、free,容易被表象蒙蔽。内存故障看不见摸不着,卡顿、延迟抖动这类隐性问题,远比直接 OOM 更消耗精力。记住核心准则:MemAvailable 才是衡量内存充裕与否的标准。遇到反复出现的隐性卡顿,不要只盯着表面指标,顺着 Swap、页面回收、内存碎片这条线索深挖,才能从根源解决问题。