交流中被问到free -h中为什么Available 比Buff/Cache小
查询发现Available估算时Buff/Cache有无法使用的部分,
是
Buff/Cache中不可立即回收(不能完全算入Available)的部分主要包括:
脏页:已被修改但尚未写入磁盘的数据。
正在被使用的页:有进程正在直接读取或写入的缓存页。
被锁定在内存中的页:通过
mlock()系统调用锁定的页。内核数据结构占用的Slab内存中的不可回收部分。
1. 脏页 - 最大的“不确定因素”
是什么:数据已在内存中被修改,但与磁盘上的版本不一致。内核必须先将它们写回磁盘,才能回收这些内存页。
影响:如果系统有大量写入操作(如数据库、日志写入),脏页会很多。回收它们需要等待I/O完成,因此不能立即提供给应用程序。
查看命令:
grep -E 'Dirty|Writeback' /proc/meminfo
输出示例:
Dirty: 12456 kB # 待写回的脏数据量 Writeback: 432 kB # 正在写回的数据量
2. 正在被使用的页
是什么:某个进程正在通过
read()或write()系统调用访问的缓存页。回收会导致进程I/O错误。影响:通常比例很小,但存在。
3. 被锁定的页
是什么:通过
mlock()系统调用明确要求常驻内存的页(如一些实时性要求高的应用、加密密钥)。影响:明确不可回收。
4. Slab内存中的不可回收部分
是什么:
/proc/meminfo中的SReclaimable(可回收Slab)被计入Buff/Cache,而SUnreclaim(不可回收Slab)则不被计入。可回收Slab:如目录项缓存(
dentry)、索引节点缓存(inode_cache)。这些可被回收,并被计入Available。不可回收Slab:一些内核数据结构占用的内存,无法回收。
查看命令:
grep -E 'SReclaimable|SUnreclaim' /proc/meminfo
内核如何计算 Available?(深入原理)
Available 的值在 /proc/meminfo 中是这样计算的(简化版):
# 查看精确值 grep Available /proc/meminfo # 内核的估算逻辑(概念上): Available = Free + (PageCache的总和 - 其中不可立即回收的部分) + (SReclaimable * 权重系数)
不可立即回收的部分 主要通过以下方式估算:
统计所有“干净”的页面(未修改的缓存),这些可以瞬间回收。
估算回收“脏页”的成本,并根据系统当前压力、I/O负载等因素,决定将多大比例的脏页计入“可用”资源。在内存压力不大时,内核可能保守估计;压力大时,会更积极地将脏页的潜在回收能力计入。
一个具体的诊断例子
假设您的系统 free -h 显示:
total used free shared buff/cache available Mem: 16Gi 10Gi 500Mi 1.0Gi 5.5Gi 4.5Gi
分析:
buff/cache有5.5Giavailable有4.5Gifree只有500Mi
计算 available 的来源:4.5Gi ≈ 0.5Gi (free) + [5.5Gi (buff/cache) - 约 1.5Gi (不可立即回收部分)]
查看这“约1.5Gi”不可回收部分的具体构成:
# 1. 查看脏页大小 cat /proc/meminfo | grep Dirty # 假设输出 Dirty: 800000 kB (约0.76Gi) # 2. 查看Slab分配 cat /proc/meminfo | grep -E 'SReclaimable|SUnreclaim' # SReclaimable: 400000 kB (约0.38Gi,这部分是buff/cache的一部分且可回收) # SUnreclaim: 200000 kB (约0.19Gi,这部分不属于buff/cache) # 3. 粗略估算 # 不可立即回收部分 ≈ 脏页 + 其他难以估算的正在使用的页 # ≈ 0.76Gi + (0.5Gi ~ 0.7Gi) ≈ 1.3Gi ~ 1.5Gi
这个估算结果与上面的分析基本吻合。
结论与建议
Available是一个智能估算值,而非简单加减。它告诉你在不引起严重I/O阻塞或进程错误的前提下,能安全分配多少内存。Buff/Cache和Available的差值,主要反映了脏页的数量和回收成本。当系统内存压力极大时,内核会启动激进的后台回写,将脏页刷入磁盘,从而将它们转变为“干净页”,增加
Available的估算值。但这个过程会导致I/O争用,可能使系统变慢。
当您需要精确分析时,请使用 cat /proc/meminfo 获取原始数据,并重点关注 Dirty, Writeback, SReclaimable 这几个指标。它们正是 Buff/Cache 中那些“看得见但暂时用不了”的部分。