加速 mdadm 软RAID的重建和重同步

在完成 mdadm构建RAID10 之后,检查 mdstat :

检查md状态
cat /proc/mdstat

可以看到 md10 在缓慢地 rsync :

检查md状态可以看到RAID正在构建
Personalities : [raid10]
md10 : active raid10 nvme11n1p1[11] nvme10n1p1[10] nvme9n1p1[9] nvme8n1p1[8] nvme7n1p1[7] nvme6n1p1[6] nvme5n1p1[5] nvme4n1p1[4] nvme3n1p1[3] nvme2n1p1[2] nvme1n1p1[1] nvme0n1p1[0]
      22499205120 blocks super 1.2 512K chunks 2 near-copies [12/12] [UUUUUUUUUUUU]
      [>....................]  resync =  0.3% (75593088/22499205120) finish=1803.0min speed=207272K/sec
      bitmap: 168/168 pages [672KB], 65536KB chunk

unused devices: <none>

这个同步时间在海量存储上非常缓慢: 例如 12块 NVMe存储 构建的 mdadm构建RAID10 ,同步速度只有 200M/s 速度,预计需要 30 小时 (1803.0min)

/proc/sys/dev/raid/{speed_limit_max,speed_limit_min} 内核参数

/proc/sys/dev/raid/speed_limit_max 是导致同步缓慢的关键,默认值是 200000 (20w,也就是转换成200MB) , 而 /proc/sys/dev/raid/speed_limit_min 默认值是 1000

修改RAID同步速度,放大10倍
sysctl -w dev.raid.speed_limit_max=2000000
sysctl -w dev.raid.speed_limit_min=10000

然后再次观察 mdstat 就可以看到同步速度大约增加了5倍(大约900MB/s),预计同步只需要6个小时(371.9min):

调整RAID同步速度,放大10倍后,同步速度加快到5倍
Personalities : [raid10]
md10 : active raid10 nvme11n1p1[11] nvme10n1p1[10] nvme9n1p1[9] nvme8n1p1[8] nvme7n1p1[7] nvme6n1p1[6] nvme5n1p1[5] nvme4n1p1[4] nvme3n1p1[3] nvme2n1p1[2] nvme1n1p1[1] nvme0n1p1[0]
      22499205120 blocks super 1.2 512K chunks 2 near-copies [12/12] [UUUUUUUUUUUU]
      [==>..................]  resync = 10.0% (2262684480/22499205120) finish=371.9min speed=906662K/sec
      bitmap: 153/168 pages [612KB], 65536KB chunk

unused devices: <none>

备注

对于现代SSD存储,默认的 mdadm 配置同步速率限制 speed_limit_max 已经不太合适,所以对于高性能存储,建议放大这个限速。这个限速也是导致RAID同步(修复或校验)缓慢的主要原因。

其他措施

备注

以下的加速措施我没有实践过,仅做记录,也许有机会可以再尝试…

设置MD设备 read-ahead

  • 设置每个MD设备 readahead (以 512字节 扇区为单位递增),可以加速同步性能:

配置MD设备 readahead 可以加速同步速度
# 设置 read-ahead 为 32 MiB,可以针对MD设备单独设置参数
blockdev --setra 65536 /dev/md0
blockdev --setra 65536 /dev/md1

设置RAID5或RAID6 stripe-cache_size

对于( 仅适用于 )RAID5和RAID6,通过调整条带缓存(stripe cache)大小(以每个设备的页为单位)可以将同步性能提高 3-6 倍。注意,该条带缓存用于同步阵列的所有写操作以及阵列降级时的所有读操作。

条带缓存的默认值是 256 ,调整范围是 17 到 32768 。在某些情况下,增加条带缓存可以提高性能,但是会占用一定的系统内存。

警告

条带缓存值设置过高可能会导致系统出现 “out of memory” 情况,所以需要按照以下公式计算:

计算条带缓存消耗的内存
memory_consumed = system_page_size * nr_disks * stripe_cache_size
设置RAID5/RAID6的MD设备条带化缓存
# 设置 md0 设备 16MiB 条带化缓存
echo 16384 > /sys/block/md0/md/stripe_cache_size

# 设置 md3 设备 32MiB 条带化缓存
echo 32768 > /sys/block/md3/md/stripe_cache_size

备注

5 Tips To Speed Up Linux Software Raid Rebuilding And Re-syncing 还提供了两个建议:

  • Disable NCQ on all disks

  • Bitmap Option

但是目前没有找到佐证资料,暂时忽略

实践警告

我在生产环境中的实践,实际上遇到一个非常糟糕的情况: 即使是默认的 {speed_limit_max,speed_limit_min} ,系统也会因为 raid-check 导致读写延迟(应用监控可以看到RT明显增加)。

这个现象似乎和理论上SSD NVMe存储 高性能不一致,在 Linux software RAID resync speed limits are too low for SSDs 提到过:

  • 实践中,某些SSD在大规模重新同步时持续写入的性能不佳(例如 SanDisk 64GB SSD SDSSSDP06 )

  • 替换的磁盘如果之前被使用过,当数据同步时,SSD会忙于擦除闪存块而导致性能极为低下

我非常怀疑是底层物理磁盘的firmware存在bug或者硬件本质上存在缺陷

参考