脏页攒到 10% 开始后台回写,攒到 20% 就阻塞写操作。模拟 4 GB 连续写:32 轮里有 11 轮被卡住——这就是【写入突然卡一下】的来源,不是磁盘坏了。
6.9 到 6.12 讲清了【缓冲与回写】的机制,这一节看它的旋钮在哪、该怎么拧。
一、六个参数
dirty_ratio(默认 20%):脏页超过总内存这个比例,写操作直接被阻塞,等回写完才能继续。 dirty_background_ratio(默认 10%):超过这个比例,后台线程开始回写,但不会阻塞你。 dirty_expire_centisecs(默认 3000,即 30 秒):脏页最多攒这么久。 dirty_writeback_centisecs(默认 500,即 5 秒):回写线程多久醒一次。 swappiness(默认 60):有多愿意把匿名页换出去(5.15 讲过)。 vfs_cache_pressure(默认 100):回收目录项与 inode 缓存的积极程度。
二、两个门槛的分工
10% 是【软门槛】:到这儿开始动手,但不打扰你。 20% 是【硬门槛】:到这儿你写的每一次都得等——因为再不写就要脏页溢出到磁盘上了。 所以【写入突然卡顿】几乎都是撞上了 20% 这个数。不是磁盘坏了,是脏页攒太多。 模拟一下:4 GB 连续写、32 轮里被卡 11 次——这个比例在真实系统里也差不多。
三、三类负载怎么调
数据库:想要【提交延迟稳定】。调低 dirty 比例、调短 dirty_expire——让脏页早点回写,别攒到硬门槛再一次性卡住。 大文件拷贝:想要【总吞吐】。调高 dirty 比例——多攒一点再一次写,减少随机写。但要接受【最后收尾时卡一下】。 突然断电不能丢:靠 fsync,不靠这些参数。参数只影响【什么时候写】,不影响【写没写下去】。
四、调参的三条纪律
一、一次只改一个。 改两个就不知道是哪个起作用。
二、量的是【你要的指标】。改吞吐就量吞吐,改延迟就量 P99 延迟——别只看平均值。
三、记住默认值再改。/proc/sys/vm/ 下每个文件都是当前值,先记下来。
还有一条:调参永远救不了错误的 IO 模式——如果程序在做小块随机写,先把模式改对,再谈调参。
五、动手 Demo:调优参数——脏页攒到多少才开始回写
这一节先把六个参数摆出来,再用一个模拟演一遍:连续写 4 GB 的时候,脏页怎么涨、什么时候会把你卡住。
total = 4096.0
bg = 0.10 * total # 软门槛
hard = 0.20 * total # 硬门槛
dirty, blocked = 0.0, 0
while written < 4096:
dirty += 128
if dirty > bg:
dirty -= 128 * 0.6 # 后台回写跟不上
if dirty > hard:
blocked += 1
dirty = hard * 0.9
实跑输出:
--------------------------------------------------------------------
调优参数——脏页攒到多少才开始回写
--------------------------------------------------------------------
① 先把参数摆出来
参数 默认量级 管什么
-----------------------------------------------------------------------------------
dirty_ratio 20% 脏页超过总内存这个比例,写就被阻塞
dirty_background_ratio 10% 超过这个比例,后台开始回写
dirty_expire_centisecs 3000(30 秒) 脏页最多攒多久
dirty_writeback_centisecs 500(5 秒) 回写线程多久醒一次
swappiness 60 有多愿意把匿名页换出去
vfs_cache_pressure 100 回收目录项与 inode 缓存的积极程度
② 演一遍:连续写 4 GB,脏页怎么涨、什么时候被卡住
指标 值
-------------------------
总内存假设 4096 MB
后台回写起点 410 MB
阻塞写的门槛 819 MB
写入轮次 32 轮
被阻塞的轮次 11 次
**注意最后一行**:**写入并不是一直顺畅的**——**脏页顶到硬门槛,写操作就得等回写。**
**这就是【写入突然卡一下】的来源**,**不是磁盘坏了。**
③ 三类负载该往哪调
负载 想优化什么 怎么调
----------------------------------------------------------------------
数据库 提交延迟稳定 调低 dirty 比例,早点回写
大文件拷贝 总吞吐 调高 dirty 比例,多攒一点再一次写
突然断电不能丢 — 靠 fsync,不靠这些参数
**注意第三条**:**调参永远替代不了 fsync。**
**参数只影响【什么时候写】,不影响【写没写下去】。**
软门槛 410 MB、硬门槛 819 MB,32 轮写入里被卡了 11 次。 注意【被卡】的意思是:写操作要停下来等回写——用户感觉就是【突然卡一下】。 这个比例取决于【写入速度】与【回写速度】谁快:写得比回写快,就一定会撞硬门槛。 所以【抖动】的本质是【生产速度超过消费速度】——这跟内存不足时的 Swap 抖动是同一个道理(5.15)。 对策只有两条:要么写慢一点(攒批),要么把回写调积极(调低门槛)。
📋 Linux 上看当前值:sysctl -a | grep -E 'dirty|swappiness|vfs_cache'——一次看全所有相关旋钮。
30 秒实验
sysctl -a | grep dirty,把这台机器的六个值抄下来。cat /proc/meminfo | grep -E 'Dirty|Writeback',看现在的脏页有多少。- 写一个大文件的同时反复读这两个数,看它什么时候涨到硬门槛。
常见误区
- 【dirty_ratio 管的是缓存大小】。它管的是脏页占内存的比例上限,是触发回写的门槛。
- 【调低 dirty 比例一定更快】。它让写更早发生、延迟更稳,但吞吐可能变低(写得碎)。
- 【调了参数就不用 fsync】。参数只管什么时候写,不管【写没写下去】。
自测三问(点开对答案)
1. dirty_background_ratio 与 dirty_ratio 差在哪? —— **前者到点开始后台回写、不阻塞你;后者到点直接阻塞写操作等回写。****一个软门槛,一个硬门槛。** 2. 写入突然卡一下是什么原因? —— **脏页撞上了硬门槛**,**写操作要停下来等回写到门槛以下。****不是磁盘坏了。** 3. 数据库为什么要把 dirty 比例调低? —— **为了让回写更早发生、更平稳**,**避免攒到硬门槛时一次性卡住,让提交延迟更稳定。**- ☐ 6.14 总结
相关笔记
- 写入文件的实验 — 写为什么怕随机
- 总结 — 整章的收口
- Swap — 同一种抖动的另一面
- 🐧 Linux是怎样工作的 · 索引