服务器监控显示Swap用了80%,不少人会立刻判断内存不够,随后执行 swapoff -a 或重启服务器。这个处理方式风险很高。Swap里可能只是很久没有访问的冷页,当前系统并没有持续换页;强行把它们全部搬回内存,反而可能触发内存耗尽和OOM Kill。
真正需要判断的不是Swap里已经放了多少数据,而是系统现在是否还在频繁换入换出、业务是否因为内存回收出现延迟,以及哪些进程的工作集正在争抢物理内存。历史占用、当前压力和性能影响必须分开看。

先读取内存与Swap全貌
先保存故障时间和基础信息:
date
uptime
free -h
swapon --show --bytes
cat /proc/meminfo | egrep 'MemTotal|MemAvailable|SwapTotal|SwapFree|SwapCached'
free 中的 MemAvailable 比单独的 free 内存更有参考价值,它估算了在不发生严重换页的情况下还能提供给新应用的内存。Linux会把空闲内存用于页缓存,used 很高本身不等于内存不足。
SwapCached 表示已经换回内存但Swap中仍保留副本的页面,这部分不能简单理解为正在重复占用。还要确认Swap是分区、文件还是压缩内存设备。使用zram时,交换发生在压缩内存中,其磁盘I/O特征与普通Swap不同。
用vmstat判断是否正在持续换页
连续采样比单次截图更重要:
vmstat 1 10
重点看 si 和 so。它们分别表示从Swap换入和换出的速率。偶发非零不一定有问题;高峰期间持续出现较大数值,同时 wa 增加、可运行队列堆积或接口延迟上升,才说明换页正在影响业务。
si/so 的单位和展示方式受工具版本影响,分析时应结合机器页大小、采样间隔和磁盘吞吐,不要用一个固定阈值套所有服务器。再查看累计计数:
grep -E 'pswpin|pswpout' /proc/vmstat
sleep 10
grep -E 'pswpin|pswpout' /proc/vmstat
两次差值能判断这10秒内是否实际发生换页。累计值很大可能只是服务器运行时间长,不能证明当前存在压力。
结合PSI与回收指标判断业务影响
支持Pressure Stall Information的内核可读取:
cat /proc/pressure/memory
cat /proc/pressure/io
some 表示部分任务因资源压力停顿,full 表示所有非空闲任务同时受阻。瞬时值要与趋势、告警窗口和业务延迟一起看。内存PSI持续升高,说明应用正在因回收或分配等待,而不仅是Swap历史占用。
再观察内核回收和缺页:
sar -B 1 10
sar -W 1 10
系统没有安装sysstat时,不要为了即时排查贸然改变生产环境,可以使用 /proc/vmstat、vmstat 和现有监控。大量直接回收、主缺页、Swap换入以及磁盘等待同时出现,证据才完整。
找出哪些进程实际占用Swap
按进程查看Swap可以使用 smem,也可以读取 /proc:
sudo smem -rs swap
没有 smem 时可检查目标进程:
grep -E 'Name|VmRSS|VmSwap' /proc/PID/status
cat /proc/PID/smaps_rollup | egrep 'Rss|Pss|Swap'
VmRSS 是进程当前驻留在物理内存中的部分,VmSwap 是该进程被换出的匿名私有页估算。共享内存、容器和内核记账会让简单求和存在偏差,不能把所有进程数字相加后当作绝对真值。
一个长期空闲进程占了较多Swap,但接口没有延迟、si/so 接近零,通常不需要紧急处理。反过来,某个进程RSS快速增长、Swap换出持续增加,且重启后很快复现,才更像内存泄漏、缓存无上限或工作集超过内存。
区分宿主机、容器与cgroup限制
容器可能在宿主机仍有可用内存时触发自己的限制。先查看容器配置和当前使用:
docker stats --no-stream
docker inspect CONTAINER --format '{{.HostConfig.Memory}} {{.HostConfig.MemorySwap}}'
cgroup v2可查看目标cgroup中的:
cat memory.current
cat memory.max
cat memory.swap.current
cat memory.swap.max
cat memory.events
路径要按实际cgroup层级定位,不能在根目录随便创建或修改文件。memory.events 中的 high、max、oom 与 oom_kill 能帮助判断是否触达限制。
容器内执行 free 看到的数值还会受到运行时和内核版本影响。排查必须同时看宿主机与cgroup,不能只凭容器内部一张截图决定扩容。
不要把swappiness当成万能开关
查看当前参数:
sysctl vm.swappiness
vm.swappiness 影响内核在回收匿名页与文件页之间的相对倾向,它不是Swap占用百分比,也不保证设置为某个数值后完全不使用Swap。工作负载、内核版本、cgroup和zram都会影响实际行为。
直接设为0可能让系统更强烈地回收文件缓存,也可能在内存紧张时更接近OOM。数据库服务器、通用Web服务器和批处理任务的合理值不同。调整前应记录 si/so、PSI、缓存命中和业务延迟,再做小范围对照。
临时修改可以用于受控测试:
sudo sysctl vm.swappiness=VALUE
确认有效后再写入 /etc/sysctl.d/ 的专用文件。不要一边改参数、一边清Swap和重启应用,否则无法判断是哪项改动产生效果。
哪些情况下需要应用优化或扩容
持续换页、内存PSI升高、接口延迟明显、OOM记录增加,且业务工作集在正常流量下长期超过物理内存,扩容才有充分依据。先检查进程上限、缓存策略、连接池、批处理并发、JVM堆、数据库缓冲池和容器限制。
journalctl -k --since '2 hours ago' | grep -Ei 'oom|out of memory|killed process'
dmesg -T | grep -Ei 'oom|out of memory|killed process'
内存问题难以复现时,可以在 萤光云 建立同版本、不同内存档位的脱敏对照,也可以在按小时计费的 LightNode 上验证工作集与Swap趋势。测试流量应经过脱敏或合成,不能复制生产账号数据。
只增加Swap适合提高短时突发的容错空间,不会让物理内存不足的长期工作集变快。Swap位于慢磁盘时,扩大容量还可能延长抖动时间。
是否可以执行swapoff
执行 swapoff 会尝试把Swap页重新放回内存。可用内存不足时可能失败,也可能触发强烈回收和OOM。生产环境不应为了把监控数字清零而执行。
必须维护Swap设备时,先确认 MemAvailable 能容纳待换回页面,并降低业务压力、准备回滚与监控。更稳妥的是逐个设备处理,而不是直接 swapoff -a。虚拟机还要确认底层存储是否正在异常,避免换页与磁盘故障叠加。
修改后怎样验收
至少跨过一个真实业务高峰,持续观察:
vmstat 5
cat /proc/pressure/memory
free -h
合格结果包括 si/so 不再持续升高、内存PSI回落、业务P95与P99延迟恢复、没有新的OOM,并且进程RSS和Swap趋势能够解释。Swap占用可能仍然保持较高,这不影响验收。
判断是否修复的标准是当前换页压力和业务延迟,而不是强行让Swap Used回到0。
常见问题
Swap用了很多但si和so一直是0,需要处理吗?
通常不需要紧急清理。先确认业务延迟、内存PSI和可用内存正常,再观察趋势。它可能只是历史冷页仍留在Swap中。
重启服务器后Swap变成0,算解决了吗?
不算。重启只清除了现场。工作集、泄漏或容器限制没有变化时,Swap还会再次增长。应在重启前保存进程与内核证据。
没有Swap是不是性能更好?
不一定。完全没有Swap会减少缓冲空间,内存突发时更容易直接触发OOM。是否保留及如何配置应根据业务工作集、延迟目标和故障容忍度决定。


