Linux cached内存可自动回收,关键看MemAvailable是否持续逼近0及OOM Killer日志;需排查overcommit设置、cgroup限制、NFS缓存、句柄泄漏及业务变更点。
内存占用持续上涨但 free 显示有大量 cached
Linux 的 cached 内存(页缓存)本就是可回收的,只要应用需要,内核会自动释放。别一看到 free -h 里 available 值低就断定“内存泄漏”。关键看 available 是否持续逼近 0,以及是否有进程因 OOM 被杀——这才是真压力。
实操建议:
- 用
free -h看available列,不是free列 - 运行
watch -n 1 'free -h; echo; cat /proc/meminfo | grep -E "^(MemAvailable|Cached|SReclaimable)"; echo; ps aux --sort=-%mem | head -5'持续观察趋势 -
Cached高但SReclaimable占比低(比如 MADV_DONTNEED 或文件被锁)
确认是否存在用户态内存泄漏:用 pmap 和 /proc/[pid]/smaps
单个进程 RSS 持续增长,且不随业务负载下降而回落,才值得怀疑泄漏。不要只看 top 的 %MEM 排序——它按比例算,小进程占比高但绝对值未必大。
实操建议:
- 先用
ps aux --sort=-rss | head -10找 RSS 最大的进程,再查其pmap -x [pid],关注mapped和written列是否异常增长 - 深入看
cat /proc/[pid]/smaps | awk '/^Size:/ {sum+=$2} END {print sum}'统计总虚拟内存;对比Rss:和Pss:,若Rss持续涨而Pss不涨,可能是共享内存或 mmap 区域在累积 - 对 Java 进程,优先用
jstat -gc [pid]看老年代是否持续增长且 GC 后不回落;对 Go 进程,检查GODEBUG=madvdontneed=1是否缺失(旧版 Go 默认不主动归还内存)
slabtop 显示 kmalloc-* 或 dentry 占用飙升
内核 slab 分配器里的对象(如 dentry、inode、ext4_inode_cache)持续增长,往往意味着文件系统层存在资源未释放:比如程序反复 open 不 close、遍历海量小文件后未释放 dcache、或 NFS 客户端元数据缓存堆积。