swappiness=1 后仍然频繁 swap 的几种隐藏内存压力来源

10次阅读

swappiness=1不能禁用Swap,极端内存压力下内核仍会换出不活跃匿名页以避免OOM;真正内存压力信号是pgscan_direct/pgsteal_direct持续非零、r值长期超CPU核数且free

swappiness=1 后仍然频繁 swap 的几种隐藏内存压力来源

swappiness=1 并不等于“禁用 Swap”

很多人误以为把 swappiness 设为 1 就能彻底避免 Swap 使用,其实不是。linux 内核在极端内存压力下仍会换出匿名页——哪怕只有一丁点空闲内存被耗尽,内核就会触发 direct reclaim,并在必要时把不活跃匿名页写入 Swap。这是保障系统不直接 OOM 的最后一道缓冲机制,无法绕过。

内存回收行为比 Swap 更早暴露压力

Swap 占用高常常是结果,不是原因。真正关键的信号藏在内存回收日志里:

  • 持续非零的 pgscan_directpgsteal_direct(查 /proc/vmstat):说明进程正在同步等待内存回收,已进入高危状态;
  • r 长期大于 CPU 核数 + free 持续低于 5%(用 vmstat 1 观察):代表就绪队列积压、可用内存严重不足;
  • dmesg | grep -i "invoked oom-killer" 出现但未 kill 进程:说明内核已判定内存临界,只是暂时靠 Swap 缓了一步。

文件缓存与 slab 占用挤压真实可用内存

即使 free -h 显示还有几 GB “used”,MemAvailable 才是系统真正能立刻分配给新进程的内存。以下情况会让它远低于预期:

  • 大量 page cache 被保留:比如频繁读大文件、日志轮转不及时、备份任务积;
  • slab 内存膨胀:尤其是 SReclaimable(可回收的 dentry/inode 缓存)过高,常见于高并发小文件访问或 NFS 挂载场景;
  • vfs_cache_pressure 默认值 100 太激进:它控制的是缓存回收强度,值越高越难释放 inode/dentry,反而推高 Swap 倾向。

容器与 cgroup 环境下的“隐形超分”

dockerkubernetes 中,Swap 行为更隐蔽:

  • 宿主机 swappiness=1,但容器没设 --memory-swappiness,它会继承宿主机值,而 cgroup v1 下 swap 限额默认不限制;
  • 多个容器共享同一台机器,各自内存 limit 总和超过物理内存,但没有统一 swap 限制,内核只能靠换出缓解;
  • 查看 cat /sys/fs/cgroup/memory/machine.slice/memory.stat 等路径,常发现 total_swap 字段非零,说明后台服务(如 systemd-journald、dbus)也在悄悄使用 Swap。
text=ZqhQzanResources