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 分钟前
ESP8266(esp-01s) 继电器控制灯具项目
后端
加瓦点灯9 分钟前
Spring AI:让大模型更好用的“桥梁”
后端
李九四27 分钟前
章节9:支持连续的加减法
后端
洛卡卡了29 分钟前
人工顶不住,机审又烧钱,我只能硬着头皮上
后端·面试·架构
Java水解40 分钟前
Spring Boot 事务详解
spring boot·后端
gauch40 分钟前
vscode 调试 Go 的配置解释(photoprism / Docker / 远程调试 / Delve)
后端·ai编程·visual studio code
轻松Ai享生活1 小时前
详解Linux LVM (Logical Volume Manager)
linux·后端
华仔啊1 小时前
别再问了!Java里这几种场景,用抽象类就对了
java·后端
guojl1 小时前
Gateway源码分析
后端·微服务
tingting01192 小时前
Spring Boot 外部配置指定不生效的原因与解决
java·spring boot·后端