导读:本期聚焦于小伙伴创作的《为什么调整 vm.dirty_background_ratio=5 后回写变频繁,延长 vm.dirty_expire_centisecs 能缓解吗》,敬请观看详情。把 vm.dirty_background_ratio 设为 5 以后,不少系统观察到后台回写线程频繁唤醒,磁盘小写入增多。这背后是脏页比例阈值降低,内核更早触发 pdflush 回写。若此时 vm.dirty_expire_centisecs 保持默认,旧脏页很快达到过期时间,进一步增加回写次数。延长该参数等于放宽脏页最长停留时间,让更多脏页有机会合并成大宗写入,减少上下文切换和寻道开销。不过延过长会带来断电丢数据风险,且内存中脏页堆积可能触发同步回写阻塞应用。理解这两个参数的耦合关系,才能根据业务 IO 模式合理调优。

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

为什么调整 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

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。