关注分享主机优惠活动
国内外VPS云服务器

系统Swap占用飙升怎么办(swap占满了会发生什么)

Linux Swap 使用暴增?一文读懂排查与调优全流程

玩VPS的站长们,是不是都遇到过这种“灵异事件”?

大半夜的,服务器监控突然报警,打开一看,负载直接拉满,SSH敲个命令都卡半天。再一看 `free -h`,内存明明还剩着呢,但Swap分区已经被啃掉好几个G。更诡异的是,MySQL直接慢成了PPT,整个网站都快打不开了。这到底是谁在“作妖”?

一看到Swap飙升,咱们的第一反应就是“内存不够了”。这话没错,但也不全对。Linux的内存管理机制那叫一个复杂,Swap只是它众多工具箱里的一个。有时候问题不是内存真的不够,而是内核的“小算盘”打得太精明,反而帮了倒忙。

别慌,今天我就以一个老站长的身份,带你把这事儿从头到尾捋一遍,彻底搞明白:

  • Swap这玩意儿到底是怎么回事?
  • 为啥它会莫名其妙地突然暴涨?
  • 什么时候该紧张,什么时候可以无视?
  • 怎么调整它,让它乖乖听话?

Table of Contents

Toggle

Swap 是内存的“备胎”,但它的性格比你想象得复杂

简单说,Swap就是把硬盘上的一块空间(可以是分区,也可以是文件)伪装成内存来用。当物理内存(真内存)吃紧时,Linux内核就会把一些它认为“不常用”的内存数据,暂时挪到硬盘上的Swap空间里,给更需要内存的程序腾地方。

这听起来很美好,对吧?但魔鬼藏在细节里。硬盘(就算是NVMe SSD)的读写速度跟内存比,那简直是拖拉机和火箭的差距。一旦系统开始频繁地在内存和硬盘之间来回倒腾数据(这个过程就叫swapping),性能就会断崖式下跌。

而且,Linux内核这老哥比你想象的要“勤快”得多。它不是非要等到内存山穷水尽才动手,而是会根据自己的一套算法,提前“整理房间”:

  • 看到某个进程虽然占着内存,但半天没活动;
  • 觉得某些内存页放太久了,像“冷数据”;
  • 预感到内存压力正在上升(但还没满);

你以为Swap是救命稻草,内核却可能把它当成了日常家政服务。


Swap 暴涨背后的可能真相

结合我自己的踩坑经验,Swap突然飙高,多半是下面几种情况:

1. 某个内存泄露的守护进程“默默长胖”

这太常见了。比如你跑的一个Python脚本、或者某个老旧的监控Agent,代码里有内存泄漏。它不会崩溃,也不怎么活动,就是安安静静地在后台越吃越多。内核一看,这货光占茅坑不拉屎,就把它挪到Swap里去了。结果就是,Swap被吃掉一大块,你还不知道是谁干的。

2. 数据库缓存+业务内存+突发流量合体爆发

你的VPS上跑着MySQL(吃内存大户),还跑着PHP/Java应用(也吃内存)。平时相安无事,突然来了波秒杀活动,并发请求暴增,应用需要更多内存处理请求。内核一看内存紧张,就把MySQL的一些缓存(它觉得不活跃)给扔到Swap里。结果呢?MySQL性能瞬间拉胯,因为它要从龟速的硬盘里读缓存,恶性循环开始了。

3. Docker、K8s 容器环境下 Swap 难以察觉

玩容器的朋友要特别注意。默认情况下,容器内部是看不到宿主机的Swap使用情况的。你可能在容器里`top`一下,感觉岁月静好,实际上宿主机已经因为某个容器的内存暴涨而疯狂swapping,导致所有容器都跟着卡顿。这锅,非常隐蔽。


判断 Swap 是否真的成了问题,不只是看“用了多少”

敲黑板,这是最关键的一点!很多人一看Swap用了几个G就慌了,其实大可不必。

Swap被用掉 ≠ 性能一定崩了

真正要命的不是“用了多少”,而是“用得有多频繁”。你得结合这几个指标来看:

  • `si / so` 的值:用 `vmstat` 命令看,`si`(swap in)和 `so`(swap out)如果持续出现大于0的数字,说明系统正在疯狂倒腾数据,这才是性能杀手。
  • `vmstat` 里的swap活动:除了si/so,还有别的指标能反映swap活跃度。
  • I/O等待:`top` 命令里 `%wa`(I/O wait)的值是不是很高?频繁swapping必然导致磁盘I/O飙升。
  • 直观感受:网站响应是不是变慢了?SSH操作是不是卡了?
  • `RES` 值:`top` 或 `htop` 里,进程的RES(常驻内存)是不是明显变小了?说明它的真内存被换出去了。

记住,Swap使用量在涨 + 系统响应明显变慢,这两个同时发生,才说明Swap真的在惹祸。


那 swapiness 到底该怎么设?

说到这,就必须提一个关键参数:`vm.swappiness`。这玩意儿就是你跟内核“讨价还价”的工具,用来告诉它到底有多“积极”地去用Swap。

  • 默认值是`60`,意思大概是“内存用到一半多点,你就开始考虑把不常用的东西扔到硬盘吧”。对桌面系统挺好,对服务器太激进了。
  • 调成`10`,意思是“内核老哥,不到万不得已,别给我动Swap,我宁愿多用点内存!”
  • 设置成`0`,在老内核上是“禁用Swap”,新内核上是“除非内存溢出(OOM),否则绝对不用”,态度最坚决。

如果你的VPS是跑数据库、网站这类对延迟敏感的应用,我个人强烈建议你大胆调低它:

bash
sysctl -w vm.swappiness=10

如果你的内存足够大,而且你确信你的应用不会内存泄漏到失控,想彻底关掉Swap也不是不行:

bash
swapoff -a

但要记住,关掉Swap等于拆掉了安全网。一旦内存真爆了,系统会直接触发OOM Killer,随机“干掉”一个进程,后果可能更严重。


查 Swap 之祸根:排查思路全流程

来,分享一套我自己的排查“三板斧”,简单粗暴但有效:

第一步:谁吃了 swap?

先揪出元凶。如果有`smem`这个工具,一条命令搞定:

bash
smem -rs swap

没有的话,用`htop`按F6,选择SWAP列排序,或者`top`之后按`f`键,选择SWAP字段,就能看到哪个进程是“吃Swap大户”。

第二步:Swap 活跃度是否高?

这个命令是我排查问题时的最爱之一:

bash
vmstat 1 5

意思是每秒刷新一次,总共看5次。你主要盯住 `si` 和 `so` 这两列,只要它们不是0,就说明系统正在玩“乾坤大挪移”,性能肯定受影响。

第三步:磁盘 IO 是不是变慢了?

bash
iostat -x 1

看对应磁盘的 `r/s` (每秒读次数) 和 `await` (平均等待时间)。如果Swap活跃,这两个值通常会异常地高。

第四步:查看进程具体 swap 内容(高阶)

对于爱钻研的朋友,还可以看看到底是进程的哪部分内存被换出去了。找到嫌疑进程的PID:

bash
cat /proc/<pid>/smaps | grep -i swap

这能让你更深入地了解问题,比如是不是把一些关键代码段给换出去了。


实战调优建议:从系统级、应用级双手出击

✅ 系统级优化

  • 调低 swappiness:这是最立竿见影的办法。
  • 升级内核:别笑,有些老内核的内存管理确实有bug,升级能解决玄学问题。
  • 用 zswap/zram:高级玩法,把要swap出去的页先在内存里压缩一下,能缓解IO压力。
  • 加钱加内存:最简单粗暴,也是最有效的终极解决方案。

✅ 应用级优化

  • 给进程上“紧箍咒”:用`ulimit`或者cgroups限制应用能使用的最大内存。
  • 优化代码:检查程序里有没有内存泄漏,特别是那些跑循环、处理大文件的代码。
  • 容器资源限制:跑容器一定要设置memory limit,别让它野蛮生长。
  • 优化服务配置:比如降低MySQL的`innodb_buffer_pool_size`,给系统和其他应用留点活路。

真实案例:一次 swap 爆炸引发的凌晨事故

我之前帮一个朋友的电商网站排查过一次故障。他们搞了个凌晨数据导出功能,结果一到点,网站就卡死。上去一看,负载爆表,Swap占了80%。

排查下来发现,Python写的导出脚本在处理大报表时内存瞬间冲高,内核就把常驻内存的PHP-FPM和MySQL的部分缓存给swap出去了。虽然导出脚本跑完内存就释放了,但被换出去的PHP和MySQL想回来就难了。大量的Swap In/Out直接拖垮了磁盘I/O,导致正常的用户访问也全部超时。

最后的解决方案很简单:

  • 给导出脚本加了队列,限制了同时执行的数量。
  • 把系统的`swappiness`从60降到了10。
  • 加了一条监控规则,只要`vmstat`里的`si/so`连续一分钟不为0就报警。
  • 从此以后,再也没出过类似问题。

Swap 不是“洪水猛兽”,也不是“好兄弟”

说到底,Swap就像你服务器里一个沉默寡言、但又很有主见的“搬运工”。你平时感觉不到它的存在,但一旦家里(内存)东西多了,它就会一声不吭地把你觉得“不重要”的东西搬到地下室(硬盘)去。

问题是,它眼里的“不重要”,可能恰恰是你业务的关键。所以,我们作为服务器的“主人”,不能对它放任不管。

别再单纯被Swap用了多少G吓到了,学会看它的“活跃度”,结合你的业务场景去调整策略,这才是真正的Pro玩法。

未经允许不得转载:主机频道 » 系统Swap占用飙升怎么办(swap占满了会发生什么)

评论 抢沙发

评论前必须登录!