应看available而非buff/cache或free;available反映可分配内存,含free与可回收缓存,>10% total即健康;available趋近0、swpd持续非零、si/so频繁跳动才表明真实内存压力。

看 available 而不是 buff/cache 或 free
绝大多数误判都源于盯着 free -h 输出里的 buff/cache 数值焦虑。只要 available 还有余量(比如 >10% total),就说明内核随时能把缓存回收给进程用,根本不需要干预。
真正要警惕的是:available 接近 0、swpd 在 vmstat 里持续非零、si/so 列频繁跳动。这时候才表明内存压力真实存在,缓存正在被主动回收,甚至开始换页。
注意:available 字段依赖内核 3.14+ 和 util-linux >= 2.20。老系统没有这列,得直接查 /proc/meminfo 里的 MemAvailable。
查 slabtop 看不可回收的缓存是否异常
buff/cache 里有一部分是可回收的 page cache,但另一部分(如 dentry、inode、ext4_inode_cache)属于 slab 分配器管理的内核对象,它们可能长期驻留、难以释放,尤其在遍历海量小文件或挂载大量 NFS 后容易堆积。
运行 slabtop -o(按 c 按缓存大小排序),重点关注:
-
dentry:路径查找缓存,超大目录树下易暴涨 -
ext4_inode_cache(或对应文件系统名):inode 缓存,批量创建/删除小文件后残留多 -
shmem_inode_cache:tmpfs 相关,Docker 容器或 systemd tmpfiles 配置不当可能推高它
如果某项占 slab 总量 70%+ 且长期不降,就要结合 lsof +D /path 或 find /proc/*/fd -ls 2>/dev/null | grep 'your_fs_type' 追踪源头。
用 vmstat 1 5 和 cat /proc/meminfo 对比瞬时压力
free 是快照,vmstat 才反映真实压力节奏。重点观察这几列:
-
b(blocked 进程数):持续 >0 表示有进程因内存分配失败而休眠 -
si/so(swap in/out KB/s):非零即已触发交换,性能拐点 -
bi/bo(block in/out):配合buff/cache高涨,若bo极低,说明缓存基本没在写回磁盘,可能是“脏页积压”或 I/O 阻塞
再打开 /proc/meminfo,对比 Buffers、Cached、SReclaimable(可回收 slab)、SUnreclaim(不可回收 slab)。如果 SUnreclaim > 1G 且 SReclaimable 很小,说明 slab 泄漏嫌疑大,不是简单 drop_caches 能解决的。
别急着 echo 3 > /proc/sys/vm/drop_caches
这条命令确实能立刻清掉 page cache 和 slab 缓存,但它会带来副作用:
- 后续所有文件读取都要重新走磁盘,业务延迟陡增,尤其数据库、日志轮转、容器镜像拉取场景
- 清完后内核会立刻重建常用缓存,几分钟内
buff/cache又涨回去——治标不治本 - 需要
root权限,且sysctl vm.drop_caches默认只对当前 session 生效,不能持久化
真要用,必须前置 sync 三次,防止未刷盘数据丢失;并且只应在确认无关键 I/O、业务低峰期执行。更稳妥的做法是调低 vm.vfs_cache_pressure(默认 100),让内核更倾向保留 dentry/inode 缓存;或增大 vm.swappiness(比如设为 10)来缓解换页冲动——但这些参数修改前务必在测试环境验证。
最常被忽略的一点:很多所谓 “buff/cache 过大”,其实是某个进程把文件 mmap 到内存后长期不释放(比如 Java 应用加载大 jar、Python pandas 读大 CSV),这类内存会计入 cache,但不会被 drop_caches 清掉,得靠 pmap -x <pid></pid> 或 cat /proc/<pid>/smaps | grep ^MMU</pid> 定位。











