4. 内存性能分析与容量规划

内存是 Linux 系统中最容易被误解的资源之一。很多运维人员看到 free 输出中 "free" 一列数值很低就认为内存不足,实际上 Linux 会主动把空闲内存用作页缓存(page cache)来加速磁盘 I/O,这部分内存随时可被回收。因此,判断内存是否真正紧张,不能只看 free 值,而要综合 available、swap 使用、缺页异常、slab 占用等多个维度。本节围绕 free、vmstat、sar、slabtop 四个工具,讲解如何分析内存使用、交换、页缓存与 slab 分配,并据此评估内存需求与 OOM 风险。

一、用 free 建立内存全景视图

free 是最直接的内存概览工具,推荐使用 free -h -w 查看人类可读且区分 buffer 与 cache 的输出:

$ free -h -w
              total   used   free   buffers   cache   available
Mem:           15Gi   9.2Gi  1.1Gi    312Mi    5.4Gi       5.6Gi
Swap:         4.0Gi   1.3Gi  2.7Gi

关键字段解读:available 是内核估算的"可分配给新应用而不触发交换"的内存量,它约等于 free + 可回收的 cache/buffer,是判断内存是否够用的第一指标。buffers 是块设备元数据缓存,cache 是页缓存(文件内容缓存)。当 available 持续低于总内存的 10%~15%,且 swap 使用量在增长,才说明内存真正吃紧。上例中 available 为 5.6Gi,占总内存约 37%,属于健康状态,尽管 free 只有 1.1Gi。

二、用 vmstat 观察动态行为

free 是静态快照,vmstat 则揭示内存的动态变化。执行 vmstat 1 5 每秒采样一次共 5 次:

$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 1331200 1152000 319488 5660672  0    0    12    48  850 1200 18  4 77  1  0
 3  0 1331200 1100800 319488 5701632  0    0     0   256 1020 1450 22  5 72  1  0

重点观察四列:si/so(swap in/out,单位 KB/s)表示换入换出速率,长期非零说明物理内存不足,系统在用磁盘当内存;free/buff/cache 反映内存分布;bi/bo 是块设备读写,若 bi 高而 cache 不增长,可能是顺序读未命中缓存。上例中 si/so 均为 0,说明虽然 swap 已用 1.3Gi,但当前没有活跃换页,属于"曾经换出、现已稳定"的状态,风险可控。若 si/so 持续大于几百 KB/s,则需立即扩容或优化应用内存占用。

三、用 sar 做历史趋势与容量基线

vmstat 只能看当下,容量规划需要历史数据。sar -r 查看内存利用率历史,sar -S 查看 swap 历史,sar -B 查看页统计:

$ sar -r -f /var/log/sa/sa15
12:00:01 AM kbmemfree kbmemused  %memused kbbuffers kbcached kbcommit %commit
08:00:01 AM   1152000   9437184     89.13    319488  5660672  8388608  52.31
12:00:01 PM    921600   9667584     91.29    319488  5767168  8912896  55.62

%memused 是已用内存占比,%commit 是已承诺内存(kbcommit)与总内存之比,反映应用申请的内存总量。若 %commit 长期接近或超过 100%,即使当前 %memused 不高,也存在 OOM 隐患,因为应用一旦真正触碰这些承诺内存就会触发分配。容量规划时,应取业务高峰时段的 %memused 与 %commit 峰值,预留 20%~30% 余量作为扩容阈值。

四、用 slabtop 定位内核内存消耗

页缓存可回收,但 slab 分配器管理的内核对象(如 dentry、inode、网络缓冲区)不一定可回收。当 free 显示 cache 很大但 available 很小,往往就是 slab 占用过多。slabtop -s c 按缓存大小排序:

$ slabtop -s c -o
 Active / Total Objects (% used)    : 1250000 / 1380000 (90.6%)
 Active / Total Slabs (% used)      : 45000 / 48000 (93.8%)
 Active / Total Caches (% used)     : 110 / 145 (75.9%)
 OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
980000 920000  93%    0.19K  49000      20    392000K dentry
210000 200000  95%    1.00K  21000      10    210000K inode_cache
 45000  40000  88%    0.50K   9000       5     45000K radix_tree_node

上例中 dentry 缓存占用约 392MB,inode_cache 约 210MB,二者合计超过 600MB。若这些缓存持续增长且不释放,会挤压可用内存。可通过 echo 2 > /proc/sys/vm/drop_caches 临时回收(生产环境慎用),或调整 vfs_cache_pressure 让内核更积极回收 dentry/inode。

内存分析四工具协同判断链 free -h -w 全景快照 · available vmstat 1 5 动态 · si/so 换页 sar -r -S -B 历史 · %commit 趋势 slabtop -s c 内核对象 · dentry 物理内存构成(示例:16GiB 总量) 应用匿名页 3.6G buffers 0.3G 页缓存 cache 5.4G(可回收) slab 0.6G 关键判断路径 available > 15% 且 si/so≈0 内存健康,cache 可回收 无需干预 available 偏低 且 si/so 持续 物理内存不足,正在换页 扩容或优化应用 %commit > 100% 或 slab 暴涨 OOM 风险高,需立即处理 调 vfs_cache_pressure / 扩容 容量规划公式(示例) 所需内存 = 应用常驻峰值 + slab 稳态 + 页缓存工作集 + 20%~30% 余量

五、OOM 风险评估与容量规划

OOM Killer 触发的前提是内核在分配内存时无法回收足够页面。评估风险需关注三点:一是 sar -r 中 %commit 是否超过 100%,说明应用承诺内存已超物理上限;二是 vmstat 中 si/so 是否持续非零,说明已进入换页;三是 dmesg | grep -i oom 是否出现历史 OOM 记录。此外,/proc/meminfo 中的 Committed_AS 与 CommitLimit 比值也是重要参考,当 Committed_AS 接近 CommitLimit 时,新的 mmap 或 malloc 可能失败。

容量规划建议采用"峰值 + 余量"法:取业务高峰时段(如 sar 记录的每日 10:00~12:00)的 %memused 与 %commit 峰值,若峰值 %memused 已达 85% 或 %commit 超过 90%,则应按 1.3~1.5 倍系数扩容。同时检查 slab 中 dentry/inode 是否异常增长,必要时调整 vm.vfs_cache_pressure(默认 100,调大更积极回收)和 vm.min_free_kbytes(保证内核预留内存)。对于 Java 等堆内存应用,还应结合 -Xmx 与 RSS 的差值判断是否存在堆外内存泄漏。

判断内存是否真的不足,记住一句话:看 available 不看 free,看 si/so 不看 swpd,看 %commit 不看 %memused。三者结合才能避免误判。
生产环境执行 echo 3 > /proc/sys/vm/drop_caches 会清空页缓存,导致后续磁盘 I/O 骤增、性能短时下降,仅建议在排查 slab 异常时临时使用,且需避开业务高峰。

综合来看,free 给出静态全景,vmstat 揭示动态换页,sar 提供历史趋势与承诺内存,slabtop 定位内核对象占用。四者配合,才能从"内存用了多少"深入到"内存被谁用了、是否可回收、会不会 OOM",从而为容量规划提供可靠依据。