1. 从一次内存告警说起:Swap 到底在忙什么
前阵子帮朋友排查一台跑得好好的服务机,监控面板突然弹出一条内存使用率超过 90% 的告警,他第一反应是“内存不够了,赶紧加条子”。我登上机器敲了free -h,发现物理内存确实快见底,但 Swap 那一行的 used 也涨了不少。他盯着那行数字问我:这玩意儿不是早就该关掉吗,怎么还在用?这个问题其实特别典型——Linux 中的 Swap(交换空间)到底有哪些作用,很多人只知道“内存不够时拿来顶一顶”,但真到线上环境,它的角色远比这句概括复杂。
先把话说清楚:Swap 是内核在物理内存(RAM)之外划出来的一块“备用存储区”,通常是一个独立分区或者一个普通文件。当内存压力上来时,内核会把一些暂时不活跃的内存页挪到这块区域,把宝贵的 RAM 腾给更急需的进程。它解决的核心问题是内存容量与进程需求之间的弹性缓冲,而不是简单地“让机器能跑更多程序”。适合读这篇内容的人,既有刚接触 Linux、被swapon命令绕晕的新手,也有在服务器上纠结要不要关 Swap 的运维同学,还有想搞明白vm.swappiness到底调多少合适的调优爱好者。
我见过太多人走两个极端:一种是把 Swap 当成万能药,内存一紧张就指望它救场;另一种是听信“SSD 时代 Swap 有害论”,上来就swapoff -a,结果某天一个内存尖峰直接把 OOM killer 招来,关键进程被干掉。这两种做法都忽略了 Swap 真正的价值边界。下面我就按自己踩过的坑和实际调优经验,把 Swap 的作用、原理、配置和排查一条条拆开讲,尽量让你看完能直接上手判断自己机器该怎么配。
2. Swap 的核心作用拆解:不只是“内存不够用”
2.1 作用一:给物理内存做弹性扩容,扛住瞬时尖峰
最直观的作用就是扩容。假设一台机器 8GB 内存,平时跑个 Web 服务加数据库也就用掉 5GB,看着挺宽裕。但编译大型项目、跑批量数据处理、或者某个进程突然申请一大块内存时,峰值可能瞬间冲到 9GB、10GB。如果没有 Swap,内核在物理内存耗尽的那一刻只能触发 OOM killer,按评分挑一个进程杀掉。有了 Swap,内核可以把一些冷页面换出去,给尖峰让路,等峰值过去再换回来。
这里的关键词是瞬时。Swap 适合应对短时间的突发压力,而不是长期超配。我一般会跟人说:Swap 是缓冲垫,不是第二块内存。你要是常年内存使用率都在 85% 以上还靠 Swap 撑着,那说明容量规划本身就有问题,加内存才是正解。判断方法很简单,看vmstat 1里的si(换入)和so(换出)两列,如果长期有稳定的非零值,说明系统在持续换页,这时候性能已经开始受影响了。
从原理上讲,内核换出的是“匿名页”——也就是没有对应磁盘文件的那些内存,比如进程的堆、栈、malloc 出来的数据。有文件背书的页(比如可执行文件、mmap 的库)在内存紧张时可以直接丢弃,需要时再从磁盘读回来,不占 Swap。所以 Swap 的大小需求,跟你机器上跑的程序类型强相关:跑一堆 Java 服务、Python 数据处理,匿名页多,Swap 需求就大;跑纯静态文件服务,匿名页少,Swap 用得就少。
2.2 作用二:让不活跃进程“让位”,提升内存整体利用率
第二个作用经常被低估:Swap 让内核可以把长时间不碰的内存页挪走,把 RAM 留给真正热的页。一个典型的例子是后台常驻的守护进程、定时任务、或者你开了很久没动的编辑器会话。这些进程占着内存但大部分时间不活跃,内核把它们换出去,前台服务就能拿到更多页缓存(page cache),磁盘读写的命中率反而更高。
这背后是内核的页面回收机制在起作用。内核维护着活跃链表和非活跃链表,页面访问频率低就会被降到非活跃链表,回收时优先从非活跃链表里挑。Swap 的存在让“换出匿名页”成为可能,否则内核只能靠丢弃文件页缓存来腾空间,一旦缓存被清空,后续读文件又得回磁盘,整体吞吐就下来了。所以在一台内存不算特别宽裕但负载波动大的机器上,合理配置 Swap 往往能让系统在压力下表现得更“从容”,而不是一有压力就手忙脚乱。
我实测过一个场景:一台 4GB 内存的小型构建机,跑持续集成任务,任务之间有明显的空闲期。配了 2GB Swap 之后,空闲期里构建守护进程的冷页面被换出,下一个任务启动时页缓存更充足,整体构建时间反而比关掉 Swap 时稳定。当然这个收益不是无条件的,前提是换出的是真冷页,而不是频繁抖动。
2.3 作用三:支撑休眠(Hibernation)的落地
桌面场景里 Swap 还有一个硬性作用:休眠。系统休眠时要把整个内存内容写到磁盘上,醒来再读回来,这块落盘区域就是 Swap。没有足够大的 Swap,休眠功能根本没法用。一般要求 Swap 大小不小于物理内存,考虑到压缩和实际使用,很多发行版默认按内存的 1 到 1.5 倍来划。
服务器上基本用不到休眠,所以这条作用对运维同学意义不大,但如果你在笔记本或工作站上装 Linux 又想要休眠,那就得老老实实把 Swap 配够。这里有个容易踩的坑:用 Swap 文件做休眠时,文件所在文件系统的类型和内核参数会影响能否正常恢复,ext4 和 btrfs 的处理方式不一样,配之前最好查一下自己发行版的文档,别配完了休眠醒不过来。
2.4 作用四:为内存回收争取时间,降低 OOM 的突发性
OOM killer 不是不能用,但它杀进程的时机和对象有时候很“随缘”,评分机制考虑的因素多,真到那一步往往已经影响到业务了。Swap 的一个隐性价值是给内核的回收路径多一个选项,让内存压力上升的过程更平缓。内核在分配内存失败时会先尝试直接回收(direct reclaim),能换出的换出、能丢弃的丢弃,实在不行才走 OOM。有 Swap 相当于多了一层缓冲,给监控告警和人工介入留出窗口。
不过要提醒一句:这个“缓冲”是有代价的。如果换出量太大,系统会陷入频繁换页的抖动状态,表现为 CPU 的wa(IO 等待)飙高、响应变慢,严重时比直接 OOM 还难受。所以我的经验是,Swap 要配,但要配合监控,把si/so和wa一起看,发现持续换页就说明该扩容或者该查内存泄漏了。
3. Swap 的形态选择与配置实操
3.1 分区还是文件:两种形态怎么选
Swap 有两种落地形态:独立分区和普通文件。分区的好处是性能略好、不经过文件系统层,坏处是调整大小麻烦,得动分区表。文件的好处是灵活,随时能建、能删、能改大小,坏处是多了一层文件系统开销,而且碎片化严重时性能会打折。
我的选择逻辑很直接:装机时规划好的、长期不动的服务器,用分区;云主机、容器宿主机、需要临时加 Swap 的场景,用文件。现在大部分云镜像默认就是文件形式,改起来方便。建 Swap 文件的基本流程是这样:
# 创建一个 2GB 的 Swap 文件 sudo fallocate -l 2G /swapfile # 权限收紧,只有 root 能读写 sudo chmod 600 /swapfile # 格式化为 swap sudo mkswap /swapfile # 启用 sudo swapon /swapfile # 写入 fstab 实现开机自动挂载 echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab这里有个细节:fallocate在部分文件系统(比如某些版本的 btrfs、zfs)上创建的文件可能不被mkswap认可,因为它分配的是“未写入”的块。遇到报错就改用dd:
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progressdd慢是慢点,但兼容性好。另外权限一定要设成 600,Swap 文件里可能有进程的敏感数据,权限放开等于把内存内容暴露给所有用户。
3.2 Swap 大小怎么定:别迷信“两倍内存”的老规矩
网上流传最广的说法是“Swap 等于内存的两倍”,这个规矩来自内存还很贵的年代,现在早就不适用了。我的实际做法是按用途分档:
| 场景 | 物理内存 | 建议 Swap | 理由 |
|---|---|---|---|
| 桌面/开发机,需要休眠 | 任意 | ≥ 内存大小 | 休眠要求 |
| 通用服务器 | ≤ 4GB | 2GB | 应对尖峰,成本可控 |
| 通用服务器 | 4GB~16GB | 2GB~4GB | 不必随内存线性增长 |
| 大内存服务器 | > 16GB | 2GB~8GB | 主要防突发,不指望它扛长期超配 |
| 容器宿主机 | 任意 | 谨慎配置 | 需结合容器内存限制一起考虑 |
核心思路是:Swap 大小取决于匿名页的峰值超出物理内存的幅度,而不是内存本身多大。一台 64GB 的机器如果常年用不到 30GB,配 4GB Swap 防个突发足够了。反过来,一台 2GB 的小机器跑内存敏感型应用,Swap 配到 2GB 甚至 4GB 都合理。
3.3 swappiness 参数:调优里最容易调错的一个
vm.swappiness控制内核换出匿名页的倾向,取值 0 到 100。默认值各发行版不同,常见是 60。很多人一看到换页就把它调成 0,以为这样就不换出了,这是个误解。swappiness=0 只是“尽量不换出匿名页”,在内存压力足够大时内核照样会换,而且极端情况下可能触发更激进的回收行为。老内核上 swappiness=0 还有过引发 OOM 的已知问题。
我的调参经验:
- 数据库服务器、延迟敏感型服务:调到 10 左右,减少换出,让热数据留在内存。
- 通用服务器:保持默认 60 或者调到 30~40,平衡内存利用和换页开销。
- 桌面机:默认值通常就挺好,不用动。
改法:
# 临时生效 sudo sysctl vm.swappiness=10 # 永久生效 echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf调完别只看数字,用vmstat 1观察si/so有没有下降,用free -h看可用内存有没有改善。参数是手段,指标才是目的。
4. 实操过程:从零给一台机器配上合适的 Swap
4.1 现状检查:先搞清楚现在是什么状态
动手之前先摸清家底。几条命令足够:
# 看内存和 Swap 总体使用 free -h # 看当前启用的 Swap 设备/文件 swapon --show # 看 Swap 的详细统计,包括换入换出总量 cat /proc/vmstat | grep -E 'pswpin|pswpout' # 看内存压力,PSI 指标更直观 cat /proc/pressure/memoryfree -h里重点看available而不是free,前者才是应用真正能拿到的内存估算。swapon --show能确认 Swap 是分区还是文件、优先级多少。/proc/pressure/memory里的some avg10如果长期偏高,说明有进程在等内存,这时候才需要考虑动 Swap 配置。
4.2 扩容与缩容:动态调整不重启
云主机上最常见的需求是临时加 Swap。按 3.1 的流程建好文件、swapon启用即可,不用重启。缩容稍微麻烦点,得先确保 Swap 里的数据能换回内存:
# 先关掉目标 Swap sudo swapoff /swapfile # 确认已关闭 swapon --show # 删除文件并清理 fstab 里的对应行 sudo rm /swapfileswapoff在 Swap 使用量很大时可能很慢,因为它要把所有换出的页读回内存,如果内存不够容纳这些页,命令会卡住甚至失败。所以缩容前先用free -h确认可用内存大于 Swap 已用量,否则先释放一些内存或者分批操作。
4.3 多 Swap 设备的优先级:一个少有人用的技巧
swapon支持给不同 Swap 设备设优先级(pri参数),数值越大越优先使用。这个特性在混合存储的机器上有用:把快的设备(比如 NVMe)上的 Swap 设高优先级,慢的机械盘设低优先级,内核会优先用快的,压力大时才动用慢的。配置写在 fstab 里:
/swapfile_fast none swap sw,pri=100 0 0 /swapfile_slow none swap sw,pri=10 0 0不过说实话,普通场景用不上这招,单块 Swap 就够了。知道有这么个东西,遇到特殊硬件组合时能想起来就行。
5. 常见问题与排查实录
5.1 Swap 用了很多,是不是有问题
这是被问得最多的问题。答案取决于“用了多少”和“怎么用的”。如果 Swap 使用量高但si/so长期接近零,说明那些页换出去之后就没人碰了,属于正常的冷页沉淀,不用管。如果si/so持续有值,系统响应变慢,那就是真压力,得查是谁在吃内存:
# 按内存占用排序看进程 ps aux --sort=-%mem | head -20 # 看每个进程的 Swap 占用 for f in /proc/*/status; do awk '/^Name|^VmSwap/{printf "%s ", $2} END {print ""}' $f; done | sort -k2 -n -r | head -20找到大户之后判断是正常业务增长还是内存泄漏。泄漏的典型特征是内存占用随时间单调上升、重启后回落,这种加 Swap 治标不治本。
5.2 关掉 Swap 之后系统反而更卡
有些教程建议 SSD 机器直接关 Swap,理由是减少写入延长寿命。这个说法在纯桌面轻负载场景下勉强成立,但在服务器上风险很大。关掉 Swap 等于把内存回收的选项砍掉一个,内核只能靠丢弃页缓存和触发 OOM 来应对压力,表现就是缓存命中率下降、磁盘 IO 上升,严重时进程被杀。现代 SSD 的写入寿命对 Swap 这点写入量完全扛得住,没必要因噎废食。真担心写入,把 swappiness 调低比直接关掉更稳妥。
5.3 常见问题速查表
| 现象 | 可能原因 | 排查命令 | 处理建议 |
|---|---|---|---|
| Swap 使用率高但系统流畅 | 冷页沉淀,正常 | vmstat 1看 si/so | 无需处理 |
| si/so 持续非零,响应变慢 | 内存不足,频繁换页 | free -h、ps aux --sort=-%mem | 扩容内存或查泄漏 |
| swapoff 卡住不动 | 可用内存不足以容纳换出页 | free -h | 先释放内存再操作 |
| 休眠后无法唤醒 | Swap 大小不足或配置错误 | swapon --show、内核日志 | 按内存 1~1.5 倍配 Swap |
| 新建 Swap 文件 mkswap 报错 | 文件系统不支持 fallocate 分配 | df -T看文件系统类型 | 改用 dd 创建 |
| 开机 Swap 没自动启用 | fstab 条目缺失或写错 | cat /etc/fstab | 补上正确条目 |
5.4 几个我踩过的坑
第一个坑是权限。有次图省事用chmod 644建 Swap 文件,结果安全扫描直接报高危,因为其他用户能读到内存换出的内容。后来养成习惯,建完立刻chmod 600,并且用ls -l确认一遍。
第二个坑是 fstab 写错导致开机进紧急模式。Swap 文件路径写错或者文件被删了但 fstab 条目还在,开机时swapon失败,某些发行版会卡在启动流程里。改 fstab 之前先备份,改完用mount -a和swapon -a验证一遍再重启。
第三个坑是容器环境。宿主机配了 Swap,但容器默认可能用不了,因为容器运行时对 Swap 有单独的限制参数。给容器配 Swap 要同时看宿主机和容器两层的配置,只改一头往往不生效。
6. 我的实际使用体会
折腾了这么多机器,我对 Swap 的态度从“能关就关”变成了“按需配置、持续观察”。它不是什么性能加速器,也不是洪水猛兽,就是一个内存管理的缓冲工具。判断标准其实就一条:看si/so和内存压力指标,有持续换页就说明配置或容量需要调整,没有就让它安静待着。真正要花心思的是搞清楚机器上跑的东西的匿名页特征,以及给监控把vmstat、/proc/pressure/memory这些指标接上,让数据说话比背参数靠谱得多。