kswapd频繁唤醒但pgpgout很低,表明脏页未及时刷出导致其等待writeback完成;主因是vm.dirty_background_ratio与vm.dirty_ratio差值过小,应适当调大前者并优化dirty_expire_centisecs和dirty_writeback_centisecs参数。

为什么 kswapd 频繁唤醒却 pgpgout 很低?
这通常不是内存不足的信号,而是 kswapd 被反复唤醒去回收页,但实际能写出交换区(swap)或回写到磁盘的页很少——说明脏页(dirty page)没被及时刷出,而 kswapd 又卡在等待 writeback 完成才能继续回收干净页。此时 vmstat 显示的 pgpgout(每秒写入 swap 的千字节数)偏低,但 pgmajfault 或 pgpgin 可能上升,/proc/vmstat 中的 pgpgout 和 pgpgin 差值大也印证了这点。
关键阈值:vm.dirty_ratio 与 vm.dirty_background_ratio
Linux 内核通过两个硬性水位控制脏页生成和刷盘节奏,它们直接影响 kswapd 是否被唤醒以及唤醒频率:
-
vm.dirty_background_ratio:达到该百分比(占可用内存)时,内核后台线程bdflush(现为writeback线程)开始异步刷脏页;不触发阻塞,但决定刷盘启动时机 -
vm.dirty_ratio:达到该百分比时,所有新写入进程会被同步阻塞,直到脏页降到该值以下;这是强制刹车点,也是kswapd最常被拖住的地方 - 两者差值过小(如仅 5%),会导致系统频繁踩到
dirty_ratio边界,迫使kswapd不得不介入回收,但它无法直接刷脏页,只能等writeback慢慢完成——于是出现“唤醒多、写出少”
如何安全调高 dirty_background_ratio?
目标是拉开两个阈值间距,给 writeback 更多缓冲时间,减少 kswapd 被脏页拖累的次数。操作前确认:/proc/sys/vm/dirty_ratio 当前值(默认 20)、/proc/sys/vm/dirty_background_ratio(默认 10):
- 若磁盘 I/O 吞吐稳定(如 NVMe 或 RAID10),可将
vm.dirty_background_ratio提至 15,vm.dirty_ratio保持 20 或提至 25(需确保有足够 swap 或内存余量) - 执行:
sysctl -w vm.dirty_background_ratio=15,并写入/etc/sysctl.conf持久化 - 避免设
vm.dirty_background_ratio ≥ vm.dirty_ratio,否则后台刷盘逻辑失效,极易触发同步阻塞 - 调整后观察
cat /proc/vmstat | grep -E "pgpgout|pgpgin|pgmajfault"和grep -i dirty /proc/meminfo,重点看Dirty:和Writeback:行是否回落更平滑
还要检查 writeback 相关参数是否拖后腿
即使 dirty ratio 设置合理,如果 writeback 自身太保守,脏页仍会堆积。重点关注:
-
vm.dirty_expire_centisecs(默认 3000 = 30 秒):脏页在内存中最多存活时间。若业务写入突发性强,30 秒可能太长,建议降至1500(15 秒)加快过期驱逐 -
vm.dirty_writeback_centisecs(默认 500 = 5 秒):writeback线程唤醒间隔。5 秒对高吞吐场景偏慢,可尝试设为100(1 秒),让刷盘更积极 - 注意:这两个值单位是厘秒(centiseconds),不是毫秒;改完用
sysctl -p生效 - 不要盲目调低
vm.dirty_expire_centisecs到 100 以下,否则可能引发大量短生命周期脏页反复刷盘,反而抬高 I/O 延迟
真正卡住 kswapd 的往往不是内存总量,而是脏页生命周期和刷盘节奏之间的错配。调阈值只是表,理清 dirty → writeback → kswapd 这条链上谁在等谁,才是关键。










