Kernel dirty
跳转到导航
跳转到搜索
“**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)。