swap波动主因是脏页积压而非swappiness,需优先检查dirty与memavailable比值、pgpgout突增、d状态进程及i/o延迟,再依存储类型调优dirty_background_ratio/dirty_ratio,并配合dirty_expire_centisecs、swappiness等参数协同控制回收节奏。

swap置换波形本身不是由 dirty_background_ratio 直接控制的,它反映的是内存压力下 page reclaim(页回收)与 swap 换出的节奏;而 dirty_background_ratio 管的是脏页刷盘行为——二者路径不同,但存在强耦合:当脏页堆积→触发同步阻塞→应用写入变慢→内存回收压力上升→swap 活动加剧。所以监控和调优这些参数,本质是“掐住脏页这个上游开关”,间接平抑 swap 波动。
先看是不是脏页在推高 swap 活动
别一看到 swap 使用率上扬就调 swappiness。先验证脏页是否成了瓶颈:
- 运行
grep -i dirty /proc/meminfo,重点关注Dirty:和MemAvailable:的比值。若 Dirty 长期 > 5% MemAvailable,且pgpgout(/proc/vmstat 中)每秒突增又归零,说明后台刷盘不稳,脏页反复积压→内核被迫更激进回收→swap 被连带拉高 - 用
pidstat -d 1观察是否有进程频繁进入 D 状态;同时iostat -x 1显示 await > 10ms、%util 接近 100%,基本确认 I/O 卡在脏页刷盘环节,进而诱发 swap 回收压力 - 检查
cat /proc/sys/vm/swappiness和vm.dirty_ratio是否冲突:例如 swappiness=60 + dirty_ratio=90,会导致系统一边攒大量脏页,一边又因内存紧张疯狂换出干净页——swap 波形尖锐、高频,这是典型参数打架
按业务写负载匹配 dirty_background_ratio 与 dirty_ratio
这两个值设得不合理,会放大 swap 波动幅度:
- SSD/NVMe 服务器:建议
vm.dirty_background_ratio = 5,vm.dirty_ratio = 10。早启动后台刷盘,避免脏页冲到熔断线再触发同步阻塞,从而减少因写卡顿引发的内存回收雪崩 - HDD 场景:设为
vm.dirty_background_ratio = 3,vm.dirty_ratio = 10。虽然 HDD 不适合高频小刷,但过高的 background 值(如默认 10)会让后台“懒惰”,等脏页快满才动,结果就是 burst 式刷盘+瞬时内存回收压力+swap 尖峰 - 混合写入服务(如日志聚合+数据库):取折中
vm.dirty_background_ratio = 8,vm.dirty_ratio = 15,并配合vm.swappiness = 10,把 swap 当作最后防线,而非日常调节器
联动 dirty_expire_centisecs 和 dirty_writeback_centisecs 控制脏页“生命周期”
只调 ratio 不控时间,脏页可能“赖着不走”,持续占用内存、挤压 swap 空间:
-
vm.dirty_expire_centisecs = 1000(10 秒):强制脏页在内存中最多存留 10 秒,防止某次批量写入后脏页滞留数分钟,拖慢整体内存周转 -
vm.dirty_writeback_centisecs = 100(1 秒):让 flush 线程每秒唤醒一次,细粒度消化脏页,避免“攒够了才猛干”,造成内存回收节奏被打乱、swap 曲线锯齿化 - 若观察到 swap 换出集中在固定时间点(如每 30 秒一次),大概率是
dirty_expire_centisecs过长(默认 3000),导致大量脏页在同一周期老化、被集中回收
配合 swappiness 和 vfs_cache_pressure 把握回收优先级
当 dirty 页面过多,内核回收时需决定:该换出匿名页(→swap),还是回收 page cache(→释放干净页)?这由以下参数协同决定:
-
vm.swappiness = 10:大幅降低 swap 倾向,迫使内核优先回收 file-backed page cache(包括脏页刷完后的干净缓存),而不是急着换出进程内存 -
vm.vfs_cache_pressure = 50:减缓 dentry/inode 缓存回收速度,保留更多元数据缓存,间接减少 write path 上的内存分配开销,缓解整体内存压力,削弱 swap 启动动机 - 注意:若
swappiness过低(如 0)且dirty_ratio过高,可能导致 OOM Killer 被触发——因为内核宁死也不 swap,又无法及时刷脏页,最终内存耗尽











