内存占用高和Swap频繁使用,这两件事在监控图上经常同时出现,但它们的因果关系比大多数人以为的要微妙。内存高不一定会导致Swap频繁读写,Swap被用上了也不代表系统正在受苦。真正需要盯住的,不是free里那个不断缩小的available数字,而是vmstat输出里si和so两列是否持续不为零。这两列才是判断“内存压力是否已经转化为性能问题”的硬指标。
Swap被用了一点,不等于出了问题
Linux内核对内存的管理方式容易让人产生误解。它不会让物理内存闲着,空闲的部分会被拿去做文件缓存,加速磁盘读写。同时,内核也会主动把一些长期不活跃的内存页换到Swap里,哪怕物理内存还有富余。这种“预防性换出”是正常行为,目的是给真正需要内存的进程腾出空间。
所以你在free -h里看到Swap的used列不是零,完全不必慌张。判断标准不在“用了多少Swap”,而在“Swap是否在被频繁地读写”。si是每秒从Swap读入内存的数据量,so是每秒从内存写入Swap的数据量。如果swpd(已使用的Swap总量)不为零,但si和so长期保持为零,说明那些被换出的页安安静静地躺在磁盘上,没有任何进程急着把它们读回来。这种状态下,Swap的存在没有对性能造成任何可感知的影响。
si/so持续活跃才是真正的警报
当si和so开始持续出现非零值,性质就变了。so持续偏高,通常意味着有进程在不停地分配内存,物理内存装不下,内核只能把一些页写到Swap里去腾地方。长时间的高so值可能表示应用程序正在泄漏内存,泄漏的内存正在被换出。这不是Swap本身的问题,是那个在泄漏的进程在逼内核做搬运工。
si持续偏高则往往对应另一种场景:之前被换出到Swap的进程,现在突然要干活了。它需要把自己的内存页从磁盘读回来,而读磁盘的速度比读内存慢几个数量级。用户侧的感受就是“这个服务刚才还好好的,怎么突然卡住了”。如果si和so同时长期偏高,这是交换震荡的证据,说明系统的物理内存不足以容纳当前的工作集,需要加内存了。
一个更具体的操作建议:执行vmstat 1 5,观察si和so列,如果这两列在多个采样间隔内持续出现较高的数值(每秒几十或上百),说明系统正在频繁地使用硬盘作为虚拟内存,这是内存不足并已影响性能的明确信号。
内存高但si/so为零,和内存高且si/so飙升,是两码事
把这两个维度放在一起看,判断逻辑就清晰了。
第一种情况:内存占用高,available偏低,但si和so几乎为零。这说明物理内存确实被占用了不少,但内核还没有被迫进行大规模的换入换出。占用内存的那些东西——可能是应用进程,可能是文件缓存——暂时处于一个“占着但没在激烈争抢”的状态。这时候需要关注的是趋势:available是在缓慢下降还是稳定在一个低位?如果稳定,可以继续观察;如果持续下降,离si/so飙升就不远了。
第二种情况:内存占用高,同时si和so持续活跃。这就是需要立刻动手的信号。内核已经在物理内存和磁盘之间来回搬运数据了,每一次搬运都是一次额外的I/O。如果Swap所在的磁盘本身就不快(VPS上很常见),这种搬运的代价会被进一步放大。si和so同时持续偏高,证明存在交换震荡,可能需要安装更多RAM,因为没有足够的内存容纳工作集。
第三种容易被忽略的情况:内存看起来还有余量,但so已经在动了。这通常指向vm.swappiness这个参数。它的默认值在不同发行版上不一样,有的设30,有的设60。值越高,内核越倾向于把匿名页换出到Swap,哪怕物理内存还有空闲。如果一台VPS的内存并不紧张,但so时不时地跳一下,检查一下/proc/sys/vm/swappiness,把它调到10左右,往往能减少这种不必要的换出。但需要说清楚:调低swappiness只是改变内核的倾向性,如果物理内存确实不够用,它救不了你。极端情况下把swappiness设成0,内核在内存耗尽时仍然会进行换出,只是会更晚才开始。
怎么动手看?不需要复杂的工具链,两条命令足够。
先看全局状态:
free -h
vmstat 1 5
free -h看available那一列,它比free列更有参考价值。available表示在不触发大量交换的前提下,还能分配给新进程的内存预估量。如果它持续低于总内存的10%,系统已经处在内存压力的边缘。
vmstat 1 5每秒采样一次,连续五次。重点关注si、so和wa三列。si/so判断Swap读写强度,wa(I/O等待)判断磁盘是否已经成为瓶颈。如果si/so活跃的同时wa也偏高,说明Swap的读写正在拖慢整个系统。
再看是谁在占用内存和Swap:
ps aux --sort=-%mem | head -10
for pid in $(ls /proc | grep '^[0-9]'); do
awk -v p=$pid '/VmSwap/ {print p, $2, "KB"}' /proc/$pid/status 2>/dev/null
done | sort -k2 -nr | head
第一条命令列出物理内存占用最高的进程。第二条遍历/proc,把每个进程的VmSwap值抽出来排序,看谁在被换出到Swap。如果某个进程的VmSwap很大,同时它的RSS也在持续增长,内存泄漏的嫌疑就很高。如果VmSwap大的进程本身已经很久没有活动,那它只是被内核“冷藏”了,不一定是问题。
Swap频繁使用和内存占用高之间,隔着一个si/so的距离。内存高是状态,si/so持续活跃是后果。状态本身不一定会伤害你,后果才会。一台VPS的available只剩两百兆但si/so为零,它可能还能安稳地跑很久;另一台available还有一个G但so每秒都在往Swap写几百KB,它的磁盘I/O已经在替内存还债了。看监控的时候,与其盯着free里那个不断缩水的数字焦虑,不如把vmstat的si/so列加到常驻面板里。那两列安静的时候,内存高点就高点;那两列开始动了,才是该动手的时候。
推荐文章