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。
五、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 的差值判断是否存在堆外内存泄漏。
echo 3 > /proc/sys/vm/drop_caches 会清空页缓存,导致后续磁盘 I/O 骤增、性能短时下降,仅建议在排查 slab 异常时临时使用,且需避开业务高峰。综合来看,free 给出静态全景,vmstat 揭示动态换页,sar 提供历史趋势与承诺内存,slabtop 定位内核对象占用。四者配合,才能从"内存用了多少"深入到"内存被谁用了、是否可回收、会不会 OOM",从而为容量规划提供可靠依据。