首页/系统/服务器硬件与 RAID 速查/整条带写与读改写(RMW)
RAID 级别与计算68 条

整条带写与读改写(RMW)

写满一整条带时控制器直接计算新校验写入,无需读取旧数据;跨条带或部分条带写则要先读旧数据与旧校验再合并,这是 RAID 5/6 写性能差异的根源。

整条带写与读改写

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

决定写路径的因素

请求大小达到或超过条带宽度的整数倍,才可能整条带落盘
对齐情况分区、文件系统块与请求偏移未对齐时会退化为跨条带写
并发程度多路并发合并在缓存中也可能凑成整条带,但不可依赖
条带宽度条带元素 × 数据盘数,是判断请求是否足够大的尺子

怎么创造更多整条带写

  • 按条带宽度对齐分区、文件系统块与上层卷条带
  • 批处理类业务尽量用大块顺序写(备份、转码、日志归档)
  • 依靠带保护的写缓存合并随机写,但要把缓存策略与保护状态一起管
  • 数据库与虚拟化场景关注写放大:把小随机写合并成更大的写单元
日志、数据库等小写场景把条带与文件系统块调小反而更有利;批量顺序写场景倾向大条带,两类业务混在同一阵列时要按主要负载定参数。

易错点

  • 在 RAID 5 上跑 4KB 小块随机写且对齐错误:每个写都触发读改写,性能与 RAID 0 差距巨大
  • 测试时忘记 oflag=direct 或 direct=1:页缓存吸收了写操作,测不出阵列的真实行为
  • 认为条带越大越好:小写密集型业务配大条带会让每笔请求都只落在一块盘上
  • 忽略上层条带叠加:逻辑卷或分布式文件系统再切条带后,两层参数不匹配会把对齐效果抵消
  • 只按容量规划不考虑写路径:容量够用但写性能不达标,后期只能靠加缓存或换级别补救

数据来源与参考

  • 《The RAID Book》(read-modify-write)
  • Broadcom MegaRAID 用户指南
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌