Linux Swap 详解 (2) - 配置与优化

详细讲解内核的 swap 行为机制常用调优开关在 SLES 上怎么查配置与用量/怎么改 。最后附实战小抄常见场景建议


1) 内核的 Swap 行为(怎么决定"换出/换入")

  • 目标:在内存紧张时回收匿名页(anonymous pages)以维持可用内存与缓存命中率,避免 OOM。

  • 优先回收顺序(简化理解)

    1. 回收页缓存(file cache:可从磁盘重读的页面)。
    2. 如果匿名页压力仍高 → 换出(swap out)匿名页,把其内容写到 swap 空间。
    3. 如果回收/换出仍无法满足水位线(watermarks) → 触发 direct reclaim ,甚至 OOM Killer
  • 参与组件

    • kswapd:后台页面回收守护,按水位线扫描 LRU(active/inactive 列表)。
    • LRU 列表:匿名页/文件页各有 active 与 inactive 两套 LRU,内核按访问频率和脏页情况移动页面。
    • Direct reclaim:分配内存的进程自己参与回收,可能导致明显延迟。
    • NUMA:优先在本节点回收,不足才跨节点迁移/回收。
    • THP(透明大页)被换出前通常会被拆分为 4K 页。
  • 换入/换出指标

    • swap out :把匿名页写到 swap(vmstatso)。
    • swap in :访问换出的页,再从 swap 读回(vmstatsi)。
    • si/so 长时间持续通常意味着内存压力大或参数不合适。

2) 关键调优开关(/proc/sys/vm/*)

  • vm.swappiness(0--100,默认 60)

    • 数值高:更积极换出匿名页,留更多页缓存。
    • 数值低:尽量少换匿名页(但不是完全不换)。
    • 经验:数据库/延迟敏感应用 1--10;通用服务器 30--60;桌面 60 附近。
  • vm.vfs_cache_pressure(默认 100)

    • 越大越积极回收 inode/dentry 缓存。I/O 密集型可适当降低以保留缓存。
  • vm.watermark_scale_factor / vm.min_free_kbytes

    • 控制回收触发的"余量"。在高内存主机上,适当调大 min_free_kbytes 可减轻抖动。
  • vm.dirty_*dirty_ratio / dirty_background_ratio 等)

    • 影响脏页回写节奏,与 swap 没直接关系,但会影响整体回收压力。
  • vm.page-cluster

    • 影响 swap 的读聚合大小(换入时的预读页数),默认 3(2^3=8 页)。
  • zswap / zram(可选)

    • zswap:匿名页先压缩后放内存后备区,必要时才写物理 swap,减少 I/O。
    • zram:在内存中创建压缩块设备作为 swap,适合 I/O 受限环境。

3) 在 SLES 上如何查看与管理 Swap

3.1 查看当前 swap 配置与用量

bash 复制代码
# 列出所有 swap 设备/文件(含优先级)
cat /proc/swaps
# 或
swapon --show --bytes --priority

# 汇总:总量/已用/剩余
free -h
grep -E 'Swap(Total|Free|Cached)' /proc/meminfo

# 实时换入/换出速率
vmstat 1       # 看 si/so 列
# 或:sar(需 sysstat)
sar -W 1

# 看整体内存/回收状态
cat /proc/meminfo | egrep 'Active|Inactive|Swap|MemFree|Cached'

3.2 看系统挂载与 fstab

bash 复制代码
# 所有 swap 单元(systemd)
systemctl list-units --type=swap
# fstab 配置
grep -n swap /etc/fstab

3.3 查看/调整内核参数

bash 复制代码
# 当前 swappiness
cat /proc/sys/vm/swappiness
# 临时调整(立即生效,重启丢失)
sudo sysctl vm.swappiness=10
# 持久化(新建/修改)
echo "vm.swappiness = 10" | sudo tee /etc/sysctl.d/99-swap-tuning.conf
sudo sysctl --system

3.4 每进程使用了多少 swap?

ini 复制代码
# 列出最占 swap 的进程(需要 root)
sudo bash -c 'for f in /proc/[0-9]*/status; do
  pid=${f#/proc/}; pid=${pid%/status}
  name=$(grep -m1 ^Name: $f | awk "{print $2}")
  vswap=$(grep -m1 ^VmSwap: $f | awk "{print $2}")
  [[ -n "$vswap" ]] && echo -e "$vswap\t$pid\t$name"
done | sort -nr | head -50'

3.5 启用/关闭 swap(谨慎)

bash 复制代码
# 立刻启用所有 fstab 定义的 swap
sudo swapon -a
# 关闭所有 swap(可能触发大量换入,谨慎)
sudo swapoff -a

3.6 新建一个 swap 文件(SLES 通用)

bash 复制代码
# 例:创建 32G swapfile
sudo fallocate -l 32G /swapfile      # 或 dd if=/dev/zero of=/swapfile bs=1M count=32768
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 持久化到 fstab(优先级 100)
echo '/swapfile none swap defaults,pri=100 0 0' | sudo tee -a /etc/fstab

3.7 使用 zswap(若内核/发行版支持,SLES15 可用)

bash 复制代码
# 查看是否启用
cat /sys/module/zswap/parameters/enabled   # Y/N
# 临时启用
echo 1 | sudo tee /sys/module/zswap/parameters/enabled
# 或加到内核参数:zswap.enabled=1(下次引导生效)

统计信息通常在 debugfs/sys/kernel/debug/zswap/(需挂载 debugfs)。

3.8 使用 zram 作为压缩内存 swap(可选)

bash 复制代码
# 加载并创建一个 16G 的 zram 设备
sudo modprobe zram
sudo zramctl -f -s 16G
# 格式化为 swap 并启用
sudo mkswap /dev/zram0
sudo swapon /dev/zram0

持久化可用 systemd-zram-generator(若 SLES 仓库提供)或开机脚本。

3.9 多个 swap 的"优先级"和并发

  • 相同优先级:Linux 会**条带化(striping)**使用它们,提高并行吞吐。
  • 不同优先级:总是先用高优先级(数值越大优先级越高)。
  • 查看优先级:cat /proc/swapsPriority 列。
  • 设置优先级:/etc/fstabpri=200,或 swapon --priority 200 /dev/...

3.10 cgroup 对 swap 的限制(容器/服务)

  • cgroup v2(SLES 15 多为 v2):

    • 目录下的 memory.swap.max 设置可用 swap 上限;memory.swap.current 查看已用。
  • 判断是否 v2:mount | grep cgroup2

  • Systemd 单元里可用 MemorySwapMax=(v2)限制服务可用的 swap。


4) 实战小抄(现场排查顺序)

  1. 有没有 swap?够不够?

    c 复制代码
    swapon --show; free -h
  2. 是否在"抖"(频繁换入/换出)?

    bash 复制代码
    vmstat 1      # 看 si/so 是否持续非零
  3. 谁在用 swap?

    • 用上面的 per-process 脚本找大头。
  4. 是否 swappiness 太高/太低?

    bash 复制代码
    cat /proc/sys/vm/swappiness
  5. I/O 是否跟不上(swap 设备很慢)?

    • iostat -xz 1(来自 sysstat 包),看 swap 设备的等待。
  6. 是否需要启用 zswap/zram 来减 I/O?

    • 适合云主机/慢盘场景。

5) 常见场景建议

  • 数据库/低延迟服务vm.swappiness=1~10,尽量避免匿名页换出;swap 只作保险。
  • 通用应用服务器vm.swappiness=30~60,保留一定页缓存。
  • 容器平台 :考虑用 cgroup v2 控制每个服务的 MemoryMax/MemorySwapMax
  • I/O 受限(云盘/机械盘) :启用 zswap 或小容量 zram,减少物理交换写入。
  • 超大内存主机 :适当增大 vm.min_free_kbytes(保持更高的可用水位,降低抖动)。
相关推荐
小咕聊编程1 小时前
【含文档+源码】基于SpringBoot的过滤协同算法之网上服装商城设计与实现
java·spring boot·后端
追逐时光者7 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_7 小时前
敏捷开发流程-精简版
前端·后端
苏打水com8 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧9 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧9 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧9 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧9 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧9 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng10 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端