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

swappiness=1 并不等于“禁用 Swap”
很多人误以为把 swappiness 设为 1 就能彻底避免 Swap 使用,其实不是。Linux 内核在极端内存压力下仍会换出匿名页——哪怕只有一丁点空闲内存被耗尽,内核就会触发 direct reclaim,并在必要时把不活跃匿名页写入 Swap。这是保障系统不直接 OOM 的最后一道缓冲机制,无法绕过。
内存回收行为比 Swap 更早暴露压力
Swap 占用高常常是结果,不是原因。真正关键的信号藏在内存回收日志里:
-
持续非零的
pgscan_direct和pgsteal_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 环境下的“隐形超分”
在 Docker 或 Kubernetes 中,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。










