Linux服务器Swap交换分区是什么?配置方法与性能影响

买服务器时经常看到"2G 内存 + 2G Swap"这类配置,很多人以为 Swap 是额外的内存,能当内存用,于是把它配得很大,结果服务器一卡就疯狂读写磁盘,反而更慢。也有人听说"Swap 会拖慢性能",干脆全部关掉,结果内存一紧张进程直接被 OOM 杀掉,业务中断。

Swap 到底该不该开、开多大、什么时候它是救命的、什么时候它是拖后腿的,这些问题没有一刀切的答案,取决于你的内存大小、磁盘类型和业务特征。这篇文章讲清楚 Swap 的作用和原理,给出不同场景下的大小建议和 vm.swappiness 的调法,手把手演示创建 swap 文件(包括 fallocate 和 dd 的坑),最后分析它对性能的真实影响,以及什么时候该用、什么时候不该用。

Swap 是什么,为什么需要它

Swap(交换空间)是磁盘上的一块区域,当物理内存不够用时,内核会把一些"暂时用不到"的内存页面挪到 Swap 上,腾出物理内存给更需要的进程。这个过程叫换出(swap out),需要时再换回(swap in)。

要理解两个关键点:

第一,Swap 不是内存的延伸,而是"内存不够时的缓冲垫"。 物理内存访问是纳秒级,SSD 是微秒级,机械盘是毫秒级,差了三到六个数量级。一旦开始频繁换入换出,程序性能会断崖式下跌。所以 Swap 的价值不在于"让内存变多",而在于:

  • 让系统在内存暂时紧张时有个缓冲,不至于立刻 OOM,给运维争取处理时间;
  • 把长期不活跃的冷数据(比如几个月没人访问的缓存页面)挪出去,给热点数据腾地方;
  • 支持休眠(hibernation,把内存整体写入 Swap),服务器一般用不到。

第二,Linux 是"用多少算多少"的按需分配。 程序 malloc 一大块内存,内核通常只分配虚拟地址,真正读写时才实际分配物理页。所以即使所有进程声明的内存总和超过物理内存,只要实际用到的没超,系统照常运行。Swap 处理的正是"实际用量"超出物理内存的情况。

# 查看当前 swap 使用情况
free -h
swapon --show
cat /proc/swaps

free -h 输出里的 Swap 那一行就是全部信息:

              total        used        free      shared  buff/cache   available
Mem:           7.7G        2.1G        512M        128M        5.1G        5.2G
Swap:          2.0G        128M        1.9G

used 持续增长是内存压力的信号,但要结合 si/so 一起看——used 有值不一定在频繁交换,只有 si/so 持续非零才说明正在拖累性能。

现代服务器该配多大 Swap

老规矩是"内存 1 倍""内存 2 倍",那是机械盘时代、内存普遍很小的时候定的,今天已经不太适用。给几个参考方向(都是经验值,不是硬标准):

物理内存 传统建议 现代通用建议 说明
< 2G 2 倍内存 2G 左右 小机器内存紧张,Swap 是必要的保命垫
2G - 8G 1 - 2 倍 2G - 4G 常用区间,够缓冲即可
8G - 32G 1 倍 2G - 8G 内存够大,Swap 主要防突发
32G - 128G 0.5 倍 4G - 8G 越大越不必大配
> 128G 争议大 0 - 8G 或用 zram 内存充裕的机器往往直接不配 Swap

近年的实践趋势是:内存充足的服务器,Swap 可以配得小一点,甚至用 zram(压缩内存)替代。 原因是 SSD/NVMe 上的 Swap 设备能提供比机械盘快得多的换页速度,同时大内存机器本身很少触发交换。所谓 zram,是在内存里划一块区域做压缩块设备当 Swap 用,换出的页面先压缩再存,能存下更多内容,读写速度也远高于磁盘 Swap:

# 查看是否加载了 zram 模块
lsmod | grep zram
sudo modprobe zram

是否用 zram 取决于发行版是否已启用(很多桌面和容器发行版默认开了)。服务器上是否启用要结合业务评估,压缩会消耗 CPU。

对于绝大多数通用业务(Web、应用服务器、中小数据库),一个朴素的规则是:留一点点 Swap 做保命缓冲,别指望它扛容量。 配 2G 到 4G,把 swappiness 调低,让它平时不动,只在真紧张时兜底。

调整 swappiness

vm.swappiness 控制内核在不活跃时把内存换出去的积极程度,范围 0 到 100,默认 60。

# 查看当前值
cat /proc/sys/vm/swappiness

# 临时修改(重启失效)
sudo sysctl vm.swappiness=10

# 永久修改
echo 'vm.swappiness = 10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system

这个值需要理解准确,因为网上有很多误传:

取值 行为 适用场景
0 尽量不换出匿名页(但内存紧张时仍可能交换,不是"禁止") 数据库等对延迟敏感的服务
1 - 10 只在内存很紧张时才换出 数据库、缓存服务、低延迟业务
60(默认) 平衡,正常回收 通用 Web、应用服务器
100 积极换出 极少用,除非内存极小且容忍慢

误区一:把 swappiness=0 当成"禁用 Swap"。它只是降低倾向,内存实在不够时内核仍然会换出,因为不换就 OOM。真要禁用是 swapoff。

误区二:在数据库服务器上直接设 0。有些数据库(如某些版本的 MySQL、Redis)会建议 swappiness 设 1 而不是 0,兼顾"尽量不换"和"内存真紧张时还有缓冲"。设 0 在极端情况下可能因匿名页无法换出而加速 OOM。

误区三:改了 /proc/sys/vm/swappiness 就以为永久生效。那是临时的,重启就没了,要写进 /etc/sysctl.d/。

创建 Swap:swap 文件实操

现在有一种趋势是用 swap 文件(swapfile)代替 swap 分区,因为它不用重新分区、随时能调大小,云服务器上几乎都这么干。步骤是:创建文件 → 格式化 → 启用 → 写 fstab。

方法一:fallocate(推荐,最快)

# 创建 4G 的 swap 文件(注意路径,/swapfile 是常见选择)
sudo fallocate -l 4G /swapfile

# 权限收紧,只有 root 能读写(重要!)
sudo chmod 600 /swapfile

# 格式化为 swap
sudo mkswap /swapfile

# 启用
sudo swapon /swapfile

# 验证
swapon --show
free -h

fallocate 是分配文件系统块,速度快,几乎瞬间完成。

方法二:dd(兼容性最好,但慢)

fallocate 在某些文件系统(比如旧的 XFS、部分网络文件系统)上可能不被支持,或者因为底层不支持 fallocate 而生成的文件有空洞,导致 swap 无法启用。这时用 dd 更稳妥,它真正写入数据:

sudo dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

dd 会实际写 4G 数据,慢一些,但避免了"空洞"问题。如果 fallocate 生成的 swap 文件启动时报 swapon: /swapfile: swapon failed: Invalid argument,多半就是空洞的锅,改用 dd 重建。

写入 fstab 实现开机自动启用

# 追加到 /etc/fstab
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 验证 fstab 无误(避免写错导致重启失败)
sudo swapon --show
sudo findmnt --verify

风险提示:/etc/fstab 写错会导致开机卡在 emergency 模式。改完务必用 findmnt --verify 校验,或者给该项加 nofail 选项:/swapfile none swap sw,nofail 0 0。回滚就是编辑 fstab 删掉那一行,然后 swapoff /swapfile。

禁用与删除

# 停用某个 swap
sudo swapoff /swapfile

# 停止所有 swap(谨慎!会瞬间占用大量内存)
sudo swapoff -a

# 删除文件(确认已从 fstab 移除后)
sudo rm /swapfile

风险提示:swapoff -a 会把 Swap 上的内容全部读回内存,如果换出的数据比空闲物理内存还多,会触发 OOM 甚至卡死。执行前先确认 free -h 里 available 足够容纳 Swap used。

创建 Swap:交换分区(老派做法)

如果还没有分区、想用独立分区,可以这么操作(切勿对已有数据的分区操作):

# 查看磁盘与分区
lsblk
sudo fdisk -l /dev/sdb

# 用 fdisk 或 parted 建一个类型为 Linux swap 的分区(类型码 82)
sudo fdisk /dev/sdb
# 在 fdisk 里:n 新建 -> t 选类型 82 -> w 保存

# 格式化和启用
sudo mkswap /dev/sdb1
sudo swapon /dev/sdb1

# 写 fstab 用 UUID 更稳妥
sudo blkid /dev/sdb1
# /etc/fstab 中写:UUID=xxxx none swap sw 0 0

风险提示:分区操作是不可逆的高危动作,fdisk 写盘后分区表立即生效,操作前必须确认磁盘上没有重要数据并做好备份。生产环境更推荐用 swap 文件,简单可控、易于回滚。

性能影响:什么时候是救命,什么时候是灾难

Swap 的代价就是磁盘速度远低于内存。影响程度取决于 Swap 所在设备:

Swap 设备 随机读写延迟量级 换页体验
NVMe SSD 几十到上百微秒 相对可用,缓存仍能感知
SATA SSD 数百微秒 可接受,但高频交换会明显变慢
机械 HDD 数毫秒到十几毫秒 灾难级,一次换页卡成幻灯片
网络存储(NFS/云盘) 视网络 最差,抖动大,不推荐做 Swap
zram(内存压缩) 微秒级 + 压缩 CPU 开销 好,但吃 CPU

机械盘做 Swap 是重灾区:一次随机读要花十几毫秒,如果是并发访问,请求排队后延迟飙升,整台机器像卡死一样。老服务器上常见的"负载不高但特别卡",往往就是 Swap 在机械盘上疯狂换页。

SSD 做 Swap 要关心磨损:Swap 的写放大很高,频繁换页会显著消耗 SSD 寿命。企业级 SSD 有高耐久度和掉电保护,问题不大;消费级 SSD 长期高频 Swap 会加速老化。同时 Swap 应放在性能最好、写寿命足够的设备上,别放在已经很繁忙的系统盘上。

判断是否正在被 Swap 拖累,看这三个指标:

free -h                # Swap used 是否持续增长
vmstat 1 5             # 看 si/so 两列(每秒换入/换出 KB)
sar -W 1 5             # sysstat 提供的换页统计

vmstat 里 si(swap in)和 so(swap out)持续非零(比如长期几百以上),说明正在频繁换页,性能必然受损。偶尔几十是正常的。so 非常高时,往往是内存压力已经很大了。

该用和不该用 Swap 的场景

场景 建议 理由
通用 Web / 应用服务器 配少量(2-4G),swappiness 中等 防突发、兜底 OOM
数据库(MySQL / PostgreSQL) 配少量或按官方建议,swappiness 调低(1-10) 换页会让查询延迟剧烈抖动
Redis / 内存数据库 基本不用 Swap,或极低 swappiness 依赖全部数据在内存,换页等于灾难
大内存计算节点(>64G) 可不配或配很小 内存充裕,很少用到
容器宿主 / Kubernetes 节点 默认不用 Swap(kubelet 默认要求关闭) 内存限制和调度依赖精确内存统计
内存极小的小机器(< 2G) 配 2 倍内存 没有 Swap 会频繁 OOM
机械盘老服务器 谨慎,宁可加内存 磁盘 Swap 性能极差

Kubernetes 节点特别注意:kubelet 默认要求关闭 Swap,因为内存调度依赖准确的内存统计。较新版本支持 Swap 但有额外配置要求。做容器平台时按集群规范来,别自作主张开 Swap。

常见问题

swappiness=0 是不是就关闭 Swap 了?

不是。它只是把内核换出的意愿降到最低,内存真正不足时仍会换出,因为内核要在"使用 Swap"和"触发 OOM"之间做选择。要真正禁用是 sudo swapoff -a,但那样内存紧张时会直接 OOM。

fallocate 建的 swap 文件起不来怎么办?

报 Invalid argument 多半是文件有空洞,底层文件系统不支持 fallocate 或生成了稀疏文件。改用 dd if=/dev/zero of=/swapfile bs=1M count=4096 重建,再 mkswap 即可。

云服务器上还需要自己配 Swap 吗?

主流云厂商的镜像通常默认已配好 Swap(多为 swap 文件),可以先 swapon --show 确认。如果没有且内存偏小,建议手动加一个 2-4G 的 swap 文件做缓冲。如果内存很充裕、业务对延迟敏感,也可以不加。

怎么知道现在有没有在用 Swap?

看 free -h 的 Swap used 和 vmstat 的 si/so。used 不为零说明有页面在 Swap 上;si/so 持续非零才说明在频繁换入换出,才会明显影响性能。另外 cat /proc/PID/status 里的 VmSwap 能看到某进程被换出了多少。

Swap 配得越大越好吗?

不是。Swap 太大会掩盖内存不足的问题,让系统在性能已经严重下降时还在硬撑,而不是尽早暴露。合理做法是配一个够缓冲的大小,把 swappiness 调低,让它在正常负载下根本不参与,只在突发或真紧张时兜底。

总结

  • Swap 是磁盘上的缓冲空间,不是内存的延伸;它的价值在于防 OOM 和缓冲冷数据,不在于"扩容内存"。
  • 现代大内存服务器的趋势是少配或不配 Swap,内存小的机器配 2 倍;通用建议是 2G-8G 做保命垫,具体看场景。
  • vm.swappiness 默认 60,数据库等延迟敏感服务调低到 1-10,但别误以为 0 就是禁用;修改要用 /etc/sysctl.d/ 持久化。
  • 建 swap 文件优先用 fallocate,遇到报错改 dd;务必 chmod 600、mkswap、写 fstab 并校验,回滚就是 swapoff 加删除。
  • 机械盘做 Swap 是性能灾难,SSD 要关心寿命,zram 是内存换压缩的替代;用 vmstat 的 si/so 判断是否正被拖累,别只看 Swap used。
  • 配了 Swap 不代表内存就够了,CPU、内存、磁盘要综合看;频繁交换说明该加内存或优化程序,而不是加大 Swap。