在 Linux 内存管理中,脏页回写机制直接影响系统的 IO 吞吐和延迟表现。当我们将 vm.dirty_background_ratio 设置为 5,意味着系统可用内存中脏页占到百分之五时,后台回写线程就开始工作。相比默认值十,这个阈值更低,所以脏页更容易被后台刷盘,直观感受就是回写动作变得频繁。此时如果 vm.dirty_expire_centisecs 仍是默认的三百,也就是三秒,那么哪怕脏页刚生成不久,只要存活超过三秒就会被归为过期数据强制写回,这就和更低的背景比例叠加,造成了小批量和多次数的回写模式。

两个参数的基本作用与关联
vm.dirty_background_ratio 控制的是触发后台回写的脏页占可用内存的比例。它是一个软阈值,只唤醒 pdflush 或 writeback 线程做异步刷盘,不会阻塞应用进程。与之相对的是 vm.dirty_ratio,那是硬阈值,超过会阻塞写操作。当我们把 background_ratio 调小,后台刷盘启动更早,理论上可以避免脏页堆积到硬阈值,但副作用是回写启动更密集。
vm.dirty_expire_centisecs 定义的是脏页的过期时间,单位是百分之一秒。系统回写线程在扫描时,会检查页的脏标记时间,如果超过这个时长,就认为必须写回。默认三百即三秒。这个参数和 background_ratio 是配合使用的:前者决定什么时候开始扫,后者决定扫出来哪些必须走。如果 background_ratio 已经让线程频繁启动,而 expire 时间又短,那每次启动都会找到一批刚过三秒的页,回写自然频繁。
为什么延长 expire 时间能缓解频繁回写
延长 vm.dirty_expire_centisecs 的本质是允许脏页在内存里多停留一段时间。假设从三百调到一千五百,也就是十五秒,那么三秒内生成的脏页不会被立刻判定过期。后台线程虽然因为 background_ratio=5 而经常醒来,但扫到的过期页变少,实际写盘量下降。更重要的是,更多脏页可以在内存中合并,比如同一个文件连续被改写,后一次覆盖前一次,最终只需写一次,这降低了磁盘写入次数。
从 IO 模式看,延长过期时间把大量零散的同步小写转化成了延迟的大块写。对于机械盘,减少寻道次数收益明显;对于固态盘,也能降低写放大。下面是一段查看和临时修改参数的命令示例,注意在 proc 文件系统中这些值以百分之一秒为单位:
# 查看当前脏页相关参数 sysctl vm.dirty_background_ratio sysctl vm.dirty_expire_centisecs # 临时将背景比例设为5,过期时间延长到1500(15秒) sysctl -w vm.dirty_background_ratio=5 sysctl -w vm.dirty_expire_centisecs=1500 # 观察回写线程行为 grep writeback /proc/$(pgrep kthreadd)/task/*/stat 2>/dev/null | head
延长参数带来的风险与边界
任何调优都是权衡。延长过期时间意味着掉电时可能丢失更多未写回的数据。如果业务是日志型强一致场景,过长的 expire 会扩大数据丢失窗口。另外,若写入速度持续高于回写速度,脏页会在内存堆积,最终触碰 vm.dirty_ratio 硬阈值,导致应用写操作被阻塞,反而引发卡顿。因此 expire 不能无限延长,需要结合内存大小和写入带宽估算。
实践中可以用以下公式粗略评估:最大允许脏页内存 = 可用内存乘以 dirty_ratio;最长堆积时间 ≈ 最大脏页内存除以平均写带宽。若延长 expire 后堆积时间逼近这个值,就有阻塞风险。建议配合 vm.dirty_writeback_centisecs 调整后台线程唤醒周期,让扫描更平滑。以下 Python 片段演示如何根据内存和带宽给出参考过期值:
# 计算建议的 dirty_expire_centisecs(示例,非生产脚本)
mem_avail_gb = 8
dirty_ratio = 0.10
write_mb_per_s = 20
max_dirty_gb = mem_avail_gb * dirty_ratio
max_dirty_mb = max_dirty_gb * 1024
max_stay_s = max_dirty_mb / write_mb_per_s
# 转换为百分之一秒
expire_centisecs = int(max_stay_s * 100)
print("建议 expire_centisecs 不超过:", expire_centisecs)
不同业务下的配置建议
对于写少读多且容忍少量丢失的缓存类服务,background_ratio 可保持较低,expire 延长到十秒以上能明显减少 IO。对于数据库这类自身有 WAL 和刷盘策略的服务,通常不让内核过多干预,会把 background_ratio 调高、expire 适度,避免双重刷盘。容器环境下还要注意,某些发行版对可用内存的计算包含 cache,会导致比例失真,需要实测回写频率而非照搬文档。
调优时应通过 sar -b 或 /proc/vmstat 中的 nr_dirty 和 writeback 计数观察效果。若发现 nr_dirty 长期低位但磁盘 util 不低,说明回写频繁但每次量少,延长时间通常有效;若 nr_dirty 经常冲高后骤降,则是硬阈值阻塞,需查写带宽而非只调 expire。理解机制再动手,才能用 vm.dirty_background_ratio 和 vm.dirty_expire_centisecs 的配合拿到稳定收益。
vm_dirty_background_ratiovm_dirty_expire_centisecspage_cache_writeback修改时间:2026-08-03 18:09:29