大量脏页堆积但 vmstat pgpgout 低的 kswapd 唤醒阈值调整

11次阅读

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

大量脏页堆积但 vmstat pgpgout 低的 kswapd 唤醒阈值调整

为什么 kswapd 频繁唤醒却 pgpgout 很低?

这通常不是内存不足的信号,而是 kswapd 被反复唤醒去回收页,但实际能写出交换区(swap)或回写到磁盘的页很少——说明脏页(dirty page)没被及时刷出,而 kswapd 又卡在等待 writeback 完成才能继续回收干净页。此时 vmstat 显示的 pgpgout(每秒写入 swap 的千字节数)偏低,但 pgmajfaultpgpgin 可能上升,/proc/vmstat 中的 pgpgoutpgpgin 差值大也印证了这点。

关键阈值: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 的往往不是内存总量,而是脏页生命周期和刷盘节奏之间的错配。调阈值只是表,理清 dirtywritebackkswapd 这条链上谁在等谁,才是关键。

text=ZqhQzanResources