“**kernel dirty 配置**” 通常指的是 Linux 内核中与 **页缓存(page cache)写回(writeback)机制** 相关的一系列参数,常见于 **/proc/sys/vm/** 目录下,比如:
```
/proc/sys/vm/dirty_ratio
/proc/sys/vm/dirty_background_ratio
/proc/sys/vm/dirty_bytes
/proc/sys/vm/dirty_background_bytes
/proc/sys/vm/dirty_writeback_centisecs
/proc/sys/vm/dirty_expire_centisecs
```
这些参数控制了内核何时、以及如何将脏页(dirty pages,即被修改但尚未写回磁盘的数据)写回到磁盘。
下面详细介绍它们的含义和使用场景 👇
---
## 🧠 基础概念
当进程写文件时,Linux 不会立刻把数据写到磁盘,而是先写到内存页缓存(page cache)里。
这些被修改但未同步到磁盘的页称为 **dirty pages**。
内核会在一定条件下触发“回写”(writeback)操作,把 dirty pages 写到磁盘中。
如果 dirty pages 太多,会影响内存可用性、系统性能甚至 I/O 延迟;
而太少,则可能浪费磁盘 I/O 带宽。
所以内核通过以下参数平衡这两者。
---
## 🔧 核心参数说明
### 1. `/proc/sys/vm/dirty_ratio`
* **作用**:系统中 dirty 页占全部可用内存的最大比例(百分比)。
* **当 dirty 页超过这个比例时,触发进程自身同步写回**。
* **默认值**:通常是 20。
📘 举例:
```
vm.dirty_ratio = 20
```
如果系统总内存 16GB,那么当 dirty 页超过 3.2GB 时,任何后续写操作都会被阻塞,直到部分脏页被写回磁盘。
---
### 2. `/proc/sys/vm/dirty_background_ratio`
* **作用**:dirty 页达到这个比例时,内核后台(flush 线程)会异步写回。
* **默认值**:通常是 10。
📘 举例:
```
vm.dirty_background_ratio = 10
```
表示 dirty 页占总内存 10% 时,后台写回线程开始工作,但不会阻塞应用。
---
### 3. `/proc/sys/vm/dirty_bytes`
* 与 `dirty_ratio` 类似,但以 **绝对字节数** 控制阈值。
* **单位**:字节。
* 优先级高于 `dirty_ratio`。
* 建议在大内存服务器上使用,因为比例值可能太大或太小。
📘 举例:
```
vm.dirty_bytes = 268435456 # 256MB
```
表示 dirty 页超过 256MB 时触发同步写回。
---
### 4. `/proc/sys/vm/dirty_background_bytes`
* 与 `dirty_background_ratio` 类似,以字节数为单位。
* 表示 dirty 页超过该值时,后台开始异步写回。
📘 举例:
```
vm.dirty_background_bytes = 134217728 # 128MB
```
---
### 5. `/proc/sys/vm/dirty_writeback_centisecs`
* **作用**:后台写回线程周期性检查 dirty 页的时间间隔。
* **单位**:1/100 秒(centisecond)。
* **默认值**:500(即 5 秒)。
📘 举例:
```
vm.dirty_writeback_centisecs = 500
```
表示每 5 秒检查一次 dirty 页并写回。
---
### 6. `/proc/sys/vm/dirty_expire_centisecs`
* **作用**:dirty 页在内存中存活的最大时间。
* 超过该时间后,即使未达阈值,也会被写回。
* **默认值**:3000(即 30 秒)。
📘 举例:
```
vm.dirty_expire_centisecs = 3000
```
表示 dirty 页在 30 秒后会被写回。
---
## ⚙️ 关系示意图
```text
应用写文件
↓
数据写入 page cache
↓
--------------------------
dirty < background_ratio → 不写回
dirty ≥ background_ratio → 后台写回线程启动
dirty ≥ ratio → 应用被阻塞并强制写回
--------------------------
```
---
## 💡 调优建议
| 场景 | 调优建议 |
| ----------------- | ----------------------------------------------------------------- |
| 高写入频率、低延迟系统(如数据库) | 降低 `dirty_ratio` 与 `dirty_background_ratio`,如 10 和 5,减少突发写回造成的延迟。 |
| 批量文件写入或大文件拷贝 | 提高 `dirty_ratio`(如 40),让系统积累更多写缓存,减少频繁 I/O。 |
| SSD 系统 | 可以略微提高比例,因为写入延迟低。 |
| HDD 系统 | 建议保守设置,避免一次性写入量太大造成 I/O 卡顿。 |
---
## 🔍 查看当前值
```
cat /proc/sys/vm/dirty_ratio
cat /proc/sys/vm/dirty_background_ratio
cat /proc/sys/vm/dirty_writeback_centisecs
```
---
## 🧩 临时与永久修改
### 临时修改(立即生效,重启后失效):
```
sysctl -w vm.dirty_ratio=15
```
### 永久修改:
在 `/etc/sysctl.conf` 或 `/etc/sysctl.d/*.conf` 中加入:
```
vm.dirty_ratio=15
vm.dirty_background_ratio=5
```
然后执行:
```
sysctl -p
```
---
## 🧠 实战案例
### 案例:数据库写延迟高
**现象:**
* PostgreSQL 写入延迟周期性上升。
* iostat 显示磁盘突发写入。
**原因:**
* dirty 页积累过多,触发同步写回(`dirty_ratio` 超限)。
**解决:**
```
sysctl -w vm.dirty_ratio=10
sysctl -w vm.dirty_background_ratio=5
```
结果:写入更平滑,系统延迟下降。
---
是否希望我帮你结合 “高 I/O wait 问题(例如 EC2+EFS 场景)” 一起讲讲这些 dirty 参数如何优化?那样我可以给你一个专门的实战优化方案。
非常好 👍 那我们接着来讲 **结合 EC2 + EFS 高 I/O wait 的 dirty 参数优化实战方案**。
这类问题你之前提到过(EC2 访问 EFS I/O wait 高、系统卡顿、load average 高等),其实和 **内核 dirty 页缓存机制** 的行为密切相关。
---
## 🧩 一、问题背景
EFS(Amazon Elastic File System) 是基于网络的 NFS 存储。
它的写入路径是这样的:
```
应用 → 内存页缓存(dirty page) → 内核写回 → 网络(NFS 客户端) → EFS 服务端
```
所以,**EFS 写延迟** 受三方面影响:
1. dirty 页写回时,**NFS I/O 延迟高**;
2. 写回过程阻塞进程,**I/O wait 上升**;
3. dirty 阈值太大导致突发写回,**系统抖动明显**。
---
## 🧠 二、内核默认行为(不适合 EFS)
在标准 Linux(尤其是 EC2 默认配置)中:
```bash
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
```
假设实例有 8GB 内存:
* dirty 页最多可以积累 1.6GB;
* 当超过 1.6GB 时,所有写进程会被阻塞;
* 然后内核突然把 1.6GB 数据通过 NFS 写入 EFS → 网络阻塞 → I/O wait 飙升。
📉 典型症状:
* `top` 显示 iowait 占用高;
* `load average` 周期性升高;
* `iostat` 中 `await`(等待时间)上升;
* EFS CloudWatch 中看到 **burst write spikes**。
---
## ⚙️ 三、优化思路
目标:
让 dirty 页积累更少、更早写回,从而使写入更平滑、I/O 更稳定。
推荐参数调整如下:
| 参数 | 默认值 | 建议值(EFS) | 说明 |
| ------------------------------ | ---- | -------- | --------------- |
| `vm.dirty_background_ratio` | 10 | **3** | 后台线程更早启动写回 |
| `vm.dirty_ratio` | 20 | **6** | 降低写缓存积累,减少突发写入 |
| `vm.dirty_expire_centisecs` | 3000 | **1500** | 15秒后强制写回旧数据 |
| `vm.dirty_writeback_centisecs` | 500 | **100** | 每1秒检查一次 dirty 页 |
| `vm.vfs_cache_pressure` | 100 | **50** | 减少元数据缓存回收频率(可选) |
设置命令:
```bash
sysctl -w vm.dirty_background_ratio=3
sysctl -w vm.dirty_ratio=6
sysctl -w vm.dirty_expire_centisecs=1500
sysctl -w vm.dirty_writeback_centisecs=100
```
或者永久写入 `/etc/sysctl.conf`:
```bash
vm.dirty_background_ratio=3
vm.dirty_ratio=6
vm.dirty_expire_centisecs=1500
vm.dirty_writeback_centisecs=100
```
---
## 📊 四、验证效果
1. 运行:
```bash
vmstat 1
```
看 `wa`(I/O wait)列是否下降。
2. 查看:
```bash
iostat -xz 1
```
观察:
* `await`(等待时间)应更稳定;
* `util`(设备利用率)峰值应降低。
3. 如果有 CloudWatch:
* EFS “DataWriteIOBytes” 图表应更平滑;
* EC2 “DiskWriteOps” 波动应减小。
---
## 🧠 五、补充优化(EFS 特有)
### 1️⃣ 使用 NFS mount 参数优化
在 `/etc/fstab` 或挂载命令中添加:
```
nfsvers=4.1,_netdev,noresvport,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2
```
说明:
* `rsize`/`wsize`:增大块传输尺寸;
* `hard`:启用重试;
* `timeo=600`:超时调整;
* `noresvport`:避免固定端口带来的冲突。
---
### 2️⃣ 检查写缓冲模式
确认挂载选项中没有 `sync`,要使用异步写:
```
mount | grep efs
```
如看到:
```
nfs4 rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,...
```
说明是异步写(✅)。
---
### 3️⃣ 对比测试
可以在调整前后使用:
```bash
dd if=/dev/zero of=/mnt/efs/testfile bs=1M count=1024 conv=fdatasync
```
比较写入时间与 iowait。
---
## ✅ 六、结论
* **默认 dirty 参数不适合 EFS 等高延迟网络文件系统**;
* **调低比例和间隔** 可显著改善 I/O wait;
* **EFS + NFS mount 优化** 能进一步提升性能;
* 调优后系统写操作更平滑、负载更稳定。
---
如果你愿意,我可以帮你写一个自动检测+优化 dirty 参数的脚本,
它能根据内存大小和挂载类型(EFS/NFS/local)自动计算合适参数。
是否帮你生成一个这样的 Bash 工具?
*** here
“什么样的 dirty 参数配置更适合 EFS 这类高延迟网络文件系统”**。
这正是很多在 AWS 上跑容器、Web 服务或 CI/CD 工具(Jenkins、GitLab Runner 等)的人经常忽略的性能关键点。
---
## 💡 一、为什么默认参数不适合 EFS?
Linux 默认 dirty 策略是为 **本地磁盘(SSD/HDD)** 设计的,假设写入延迟低、带宽高。
但 EFS 是 **NFS over network(网络文件系统)**,意味着:
* 写延迟高(>5ms 常见);
* 吞吐受限于网络;
* 写回触发时,内核可能要等待远程 ACK。
所以默认策略下:
* dirty 页积累较多(默认 10%~20% 内存);
* 一旦超过 dirty_ratio,内核会一次性写大量数据;
* 导致所有写入线程被阻塞(I/O wait 飙升);
* 系统负载周期性抖动。
---
## ✅ 二、EFS 适配原则(经验法则)
EFS 是 **高延迟 + 异步写** 场景,目标是:
> “让系统频繁地、少量地、平滑地写回,而不是一次性大量写回。”
因此参数调优目标是:
* **降低 dirty 页累积量**;
* **加快后台写回频率**;
* **减少一次性突发写入量**;
* **保证内核不阻塞应用写入。**
---
## 🧩 三、推荐参数配置(EFS 最佳实践)
| 参数 | 默认 | 推荐值(EFS) | 说明 |
| ------------------------------ | ---- | -------------- | --------------------- |
| `vm.dirty_background_ratio` | 10 | **2–3** | 让后台写回更早启动 |
| `vm.dirty_ratio` | 20 | **4–6** | 避免突发同步写回 |
| `vm.dirty_expire_centisecs` | 3000 | **1000–1500** | 脏页在 10–15 秒内强制写回 |
| `vm.dirty_writeback_centisecs` | 500 | **100** | 每 1 秒周期性触发写回 |
| `vm.dirty_background_bytes` | - | 可选,如 **64MB** | 固定后台写回阈值(大内存机器推荐) |
| `vm.dirty_bytes` | - | 可选,如 **128MB** | 固定同步写回阈值 |
| `vm.vfs_cache_pressure` | 100 | **50** | 保留更多文件系统缓存(NFS 元数据有用) |
---
## 🔧 四、示例配置
```bash
cat <<EOF | sudo tee /etc/sysctl.d/99-efs-tuning.conf
vm.dirty_background_ratio=3
vm.dirty_ratio=6
vm.dirty_expire_centisecs=1500
vm.dirty_writeback_centisecs=100
vm.vfs_cache_pressure=50
EOF
# 应用新配置
sudo sysctl -p /etc/sysctl.d/99-efs-tuning.conf
```
---
## 📊 五、为什么这些值合适
| 参数 | 原理解释 |
| ------------------------------- | ---------------------------------- |
| `dirty_background_ratio=3` | 当 dirty 页达到 3% 内存时就开始后台写回,避免积压。 |
| `dirty_ratio=6` | 写缓存不会超过 6%,即使写入速度快、网络延迟高,也不至于堆积太多。 |
| `dirty_writeback_centisecs=100` | 每 1 秒检查一次,让系统能持续写,而非积累后集中写。 |
| `dirty_expire_centisecs=1500` | 防止老脏页滞留太久,EFS 这种延迟较高的系统中可以避免写延迟突发。 |
| `vfs_cache_pressure=50` | 减少内核频繁回收目录和 inode 缓存,适合频繁访问的小文件场景。 |
---
## 🧠 六、内核行为对比(默认 vs 调优)
| 指标 | 默认值 | 调优后(EFS) |
| ------------ | -------- | -------- |
| dirty 页积累 | 高(可达几GB) | 低(几十MB) |
| 写回触发频率 | 低(5秒一次) | 高(1秒一次) |
| 每次写入量 | 大 | 小 |
| 应用写入延迟 | 周期性卡顿 | 平滑稳定 |
| 系统 iowait | 高峰周期性上升 | 平稳较低 |
| Load Average | 周期性波动 | 相对平稳 |
---
## 🧪 七、验证方法
### 1️⃣ 实时监控
```bash
watch -n1 "cat /proc/meminfo | grep -E 'Dirty|Writeback'"
```
调优后,你应该看到 `Dirty` 保持在几MB以内(非常稳定)。
### 2️⃣ I/O 观察
```bash
iostat -xz 1
```
看 `await`、`svctm`、`util`,调优后波动应小。
### 3️⃣ CloudWatch 验证
查看:
* EC2 → CPUUtilization(iowait 应下降)
* EFS → DataWriteIOBytes(更均匀)
---
## 💬 八、进阶建议
### 1. 大内存机器(>32GB)
使用字节型参数更合适:
```bash
vm.dirty_background_bytes=67108864 # 64MB
vm.dirty_bytes=134217728 # 128MB
```
### 2. 对于数据库或日志型写入
可进一步降低 dirty_ratio,比如:
```bash
vm.dirty_background_ratio=2
vm.dirty_ratio=4
```
### 3. 只读 EFS 场景
可不调 dirty 参数,仅关注缓存压力:
```bash
vm.vfs_cache_pressure=50
```
---
## 🧰 九、实战建议总结
| 目标 | 策略 |
| -------------- | --------------------------------------- |
| 平滑写入、减少 iowait | 减小 dirty_ratio 和 dirty_background_ratio |
| 避免突发写回 | 提高写回频率(dirty_writeback_centisecs 降低) |
| 降低旧页滞留 | 降低 dirty_expire_centisecs |
| 大内存系统更精准 | 使用 *_bytes 参数替代 *_ratio |
| 减少目录/元数据抖动 | 降低 vfs_cache_pressure |
---
是否希望我帮你写一个小脚本,它会自动检测系统类型(EBS 本地盘 / EFS / NFS)
然后自动应用最优 dirty 参数配置?
例如一键运行 `optimize-dirty.sh` 即完成优化(支持 rollback)。
references
Linux内存查看及一次释放Linux内存问题处理(Aliyun ecs)