整条带写与读改写
RAID 5/6 的写性能差异根源在于写路径。当一次写入覆盖整个条带时,控制器可以一次性算出新校验并直接写入所有盘,不读取旧数据;而当写入只覆盖条带的一部分(或跨条带边界)时,就必须先读旧数据与旧校验、合并计算后再写回,也就是读改写(RMW)。同一块阵列上,两种路径的物理 IO 次数能差好几倍,这也是容器与数据库常见「顺序写很快、随机写很慢」现象的原因。
两种写路径
| 场景 | 过程 | 代价 |
|---|---|---|
| 整条带写 | 新数据直接到达所有盘,校验一次算出 | 无额外读,接近全速 |
| 部分条带写 | 读旧数据 + 读旧校验 + 写新数据 + 写新校验 | 4 次物理 IO(RAID 5) |
| 跨条带写 | 涉及两个条带的部分写 | 触发两次 RMW,代价更高 |
| RAID 6 部分写 | 两套校验各自读改写 | 6 次物理 IO |
验证顺序写收益(仅测试环境)
验证顺序写收益(仅测试环境)
# 顺序写(应接近阵列带宽上限)
dd if=/dev/zero of=/mnt/raidtest/seq.bin bs=1M count=4096 oflag=direct
# 随机小写(RAID 5/6 上会明显更慢)
fio --name=randwrite --ioengine=libaio --direct=1 --rw=randwrite --bs=4k --size=1G --filename=/mnt/raidtest/rand.bin
# 注意:oflag=direct / direct=1 才会绕过页缓存,否则测不出阵列真实行为
rm -f /mnt/raidtest/seq.bin /mnt/raidtest/rand.bin决定写路径的因素
| 请求大小 | 达到或超过条带宽度的整数倍,才可能整条带落盘 |
|---|---|
| 对齐情况 | 分区、文件系统块与请求偏移未对齐时会退化为跨条带写 |
| 并发程度 | 多路并发合并在缓存中也可能凑成整条带,但不可依赖 |
| 条带宽度 | 条带元素 × 数据盘数,是判断请求是否足够大的尺子 |
怎么创造更多整条带写
- 按条带宽度对齐分区、文件系统块与上层卷条带
- 批处理类业务尽量用大块顺序写(备份、转码、日志归档)
- 依靠带保护的写缓存合并随机写,但要把缓存策略与保护状态一起管
- 数据库与虚拟化场景关注写放大:把小随机写合并成更大的写单元
日志、数据库等小写场景把条带与文件系统块调小反而更有利;批量顺序写场景倾向大条带,两类业务混在同一阵列时要按主要负载定参数。