free说内存满了,top却说很闲:被Page Cache吞掉的"假满"【转】
凌晨两点,手机震了。Zabbix告警弹出来:内存使用率 87%。
你一个激灵坐起来,SSH上去,free -h 一敲——free 列只剩 2G,buff/cache 倒是吃了 12G。心脏漏跳一拍。赶紧 top 看谁在吃内存,按 Shift+M 排个序,最大的进程才占 800M。
16G 的内存,top 说没人在用,free 命令说只剩 2G 空闲。谁在说谎?
答案:谁都没说谎,是你看错了 free 的意思。
抓手一:free -h —— 别盯着 free 列,看 available
free -h 输出大概长这样:
大部分人的眼睛盯着 free 列那个 2G——16G 的机器只剩 2G 空闲?心跳直接加速。但你往右看一列——available 写着 13G。
available 是内核自己估算的"现在能拿来给新进程用的内存"。它已经把可回收的 Page Cache、可回收的 Slab 都算进去了。available 有余量,free 列多低都不用慌。
这里要插一句:很多监控告警就是栽在这。Zabbix 常见的内存模板用 vm.memory.size[free] 或按 (total - free) 算使用率,把 buff/cache 全算成了"已用"。87% 的告警就是这么来的——(16 - 2) / 16 = 87.5%。正确做法是监控 available 或按 (total - available) 算使用率。
但这里有个坑。CentOS 6 那个年代的 free 长得不一样:
老版本的 used 把 buffers 和 cached 都算进去了,看着 used 14G 吓人。但底下那行 -/+ buffers/cache 才是真相——实际 used 4G,可用 12G。
现在你去网上搜"Linux free 命令详解",很多文章还在用老版本截图。拿老截图套新机器,结论就是反的。
free 不是在告诉你内存满了,是在告诉你它拿了多少当缓存。
抓手二:cat /proc/meminfo —— 给内存照张 X 光
free 是体检报告的摘要,/proc/meminfo 就是详细报告。关键看三个数:
Cached 是 Page Cache 的大头——你读写过的文件,内核都留一份在内存里,下次访问就不用走磁盘了。10G 的 Cached,说明你系统上跑过不少 IO。
Slab 是内核自己用的缓存,存的是 inode、dentry 这些内核数据结构。它拆成两半:SReclaimable 是可以回收的,SUnreclaim 是锁死不还的。
坑在这:很多人看 free 的 free 列低,进 meminfo 只看 Cached,发现有 10G 缓存,就判断"缓存占的,没事"。结论倒是对了,但停在这一步不够——SReclaimable 还有 1G,这 1G 也是可回收的,也是"假满"的一部分,但它没算在 Cached 里。free 的 buff/cache 列 = Buffers + Cached + SReclaimable,三个加起来才是完整的缓存占用。
反过来,有人一看 Slab 有 2G,吓得以为内核内存泄漏。但 Slab 里有 SReclaimable 和 SUnreclaim,前者随时能还,只有后者才是真占用。你得看全了再下结论。
meminfo 是 free 的 X 光片,能看到每块骨头叫什么。
抓手三:vmstat / sar —— 别看快照,看趋势
前面两个抓手看的都是"当前这一刻"的内存。但运维判断内存有没有问题,看趋势比看快照重要一百倍。
盯两列就够:si(swap in)和 so(swap out)。如果这两个一直是 0,说明内核压根没在用 swap,内存够用得很。available 高 + si/so 为 0 = 健康的缓存利用,啥都不用动。
但如果你看到 si 开始从 0 往上跳,available 在往下走——这就不一样了。内核开始从 swap 里往回搬数据,说明物理内存真的吃紧了。这时候才需要考虑加内存或者查谁在泄漏。
要是你想看历史趋势,sar -r 能给你过去一段时间的内存变化曲线。很多机房都装了 sysstat 包,数据一直在记着,就看你用不用。
这里有个大坑,必须说。有些人一看到内存告警,不管三七二十一:
echo 3 > /proc/sys/vm/drop_caches
咔,used 掉下来了,心里舒坦了。但下一秒,所有读操作要重新走磁盘,IO 直接飙起来。生产环境这么干,轻则业务变卡,重则数据库 IO 瓶颈引发连锁故障。
drop_caches 不是不能用,是别在正常运行的机器上用。排查特定问题(比如怀疑缓存数据损坏)的时候可以临时清一下,但清完别忘让它自己重新攒起来。
手动清 Page Cache 就像把抽屉倒出来找东西——找完了还得重新整理,而且整理的时候你什么都干不了。
老兵判断:看内存满不满,就三句话
干运维这些年,我总结了个三步判断法,不管多复杂的场景,这三个问题答完,结论就有了:
available 够不够? 够,就别管 free 列多低——缓存用满才是正常表现,说明你的内存没浪费。
si/so 动没动? 一直是 0,说明没在交换,内存充裕。开始跳了,才需要警觉。
有没有 OOM 日志?dmesg | grep -i oom 查一下,没杀进程就没出过事。
三个都过,监控面板上 90% 也是健康的。Linux 的设计哲学就是"闲着的内存就是浪费的内存",它拿去当缓存天经地义。
从"看 free 列脸绿"到"看 available + si/so 趋势判断",这一步跨过去,你就从初级运维进入中级了。不是技术多难,是认知得翻过来。
看内存不是看数字,是看趋势。数字骗你,趋势不会。
转自

浙公网安备 33010602011771号