![为什么 mdadm 在同步挂载时写入速度慢得无法使用?](https://linux22.com/image/543796/%E4%B8%BA%E4%BB%80%E4%B9%88%20mdadm%20%E5%9C%A8%E5%90%8C%E6%AD%A5%E6%8C%82%E8%BD%BD%E6%97%B6%E5%86%99%E5%85%A5%E9%80%9F%E5%BA%A6%E6%85%A2%E5%BE%97%E6%97%A0%E6%B3%95%E4%BD%BF%E7%94%A8%EF%BC%9F.png)
我有一个 6 磁盘 raid6 mdadm 阵列,我想对写入进行基准测试:
root@ubuntu:~# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid6 sda[0] sdf[5] sde[4] sdd[3] sdc[2] sdb[1]
1953545984 blocks level 6, 64k chunk, algorithm 2 [6/6] [UUUUUU]
由于缓存的原因,基准测试可能不准确 - 例如,请注意此处的写入速度高于应有的速度:
root@ubuntu:/mnt/raid6# dd if=/dev/zero of=delme bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.276026 s, 380 MB/s
现在我们可以很轻松地禁用每个磁盘缓存:
root@ubuntu:~# hdparm -W0 /dev/sd*
/dev/sda:
setting drive write-caching to 0 (off)
write-caching = 0 (off)
/dev/sdb:
setting drive write-caching to 0 (off)
write-caching = 0 (off)
/dev/sdc:
setting drive write-caching to 0 (off)
write-caching = 0 (off)
/dev/sdd:
setting drive write-caching to 0 (off)
write-caching = 0 (off)
/dev/sde:
setting drive write-caching to 0 (off)
write-caching = 0 (off)
/dev/sdf:
setting drive write-caching to 0 (off)
write-caching = 0 (off)
但Linux缓存仍然存在:
root@ubuntu:/mnt/raid6# dd if=/dev/zero of=delme bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00566339 s, 1.9 GB/s
要禁用 Linux 缓存,我们可以同步挂载文件系统:
mount -o remount,sync /mnt/raid6
但在此之后写成了方式比应有的速度慢:
root@ubuntu:/mnt/raid6# dd if=/dev/zero of=delme bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 23.3311 s, 449 kB/s
好像 mdadm 需要异步挂载才能运行。这是怎么回事?
答案1
提问者引述:
但Linux缓存仍然存在:
root@ubuntu:/mnt/raid6# dd if=/dev/zero of=delme bs=1M count=10 10+0 records in 10+0 records out 10485760 bytes (10 MB) copied, 0.00566339 s, 1.9 GB/s
要禁用 Linux 缓存,我们可以同步挂载文件系统:
mount -o remount,sync /mnt/raid6
这不太对……同步并不是像基准测试中那样简单地禁用缓存。它使每次写入都产生“同步”命令,这意味着将缓存全部刷新到磁盘。
这里有一个服务器,为了更好地解释:
$ dd if=/dev/zero of=testfile bs=1M count=500
500+0 records in
500+0 records out
524288000 bytes (524 MB) copied, 0.183744 s, 2.9 GB/s
$ dd if=/dev/zero of=testfile bs=1M count=500 conv=fdatasync
500+0 records in
500+0 records out
524288000 bytes (524 MB) copied, 5.22062 s, 100 MB/s
conv=fdatasync 只是表示写入后刷新,并告诉您包括刷新在内的时间。或者,您可以执行以下操作:
$ time ( dd if=/dev/zero of=testfile bs=1M count=500 ; sync )
500+0 records in
500+0 records out
524288000 bytes (524 MB) copied, 0.202687 s, 2.6 GB/s
real 0m2.950s
user 0m0.007s
sys 0m0.339s
然后根据 2.95 秒的实时时间(而不是上面的 0.2 秒)计算 MB/s。但这样比较丑陋,工作量也更大,因为 dd 打印的统计数据不包括同步。
如果您使用“同步”,您将刷新每个写入...可能这意味着每个块,这将运行非常慢。 “同步”应该只在非常严格的系统上使用,例如数据库,其中由于磁盘故障而导致单个事务的丢失是不可接受的(例如,如果我将十亿美元从我的银行账户转移到你的银行账户,并且系统崩溃,突然你有了钱,但我也有)。
这是我很久以前读过的另一种带有附加选项的解释。 http://romanrm.ru/en/dd-benchmark
还有一点需要注意:在我看来,您以这种方式进行的基准测试完全有效,尽管在许多其他人看来并不有效。但这不是实际测试。这是一个单线程顺序写入。如果您的实际用例是这样的,例如通过网络发送一些大文件,那么它可能是一个很好的基准。如果您的用例不同,例如 500 人同时上传小文件的 ftp 服务器,那么它就不是很好。
此外,为了获得最佳效果,您应使用 RAM 上随机生成的文件。它应该是随机数据,因为有些文件系统在输入零时会变得非常聪明。例如,在 Linux 上使用挂载在 /dev/ 上的 RAM 文件系统 tmpfs。它应该是 RAM fs,而不是直接使用 /dev/urandom,因为 /dev/random 真的很慢,而 /dev/urandom 更快(例如 75MB/s),但仍然比 hdd 慢。
dd if=/dev/urandom of=/dev/shm/randfile bs=1M count=500
dd if=/dev/shm/randfile bs=1M count=500 conv=fdatasync
答案2
由于同步写入强制奇偶校验计算对磁盘造成影响,因此性能急剧下降。
一般来说,计算和写入奇偶校验是一个相对较慢的过程,尤其是使用 RAID 6 时——在您的例子中,md 不仅必须将数据分割成四个块,然后还要为每个条带计算两个奇偶校验块。为了提高性能,RAID 实现(包括 md)将在内存中缓存最近使用的条带,以便将要写入的数据与现有数据进行比较,并在写入时快速重新计算奇偶校验。如果将新数据写入缓存的条带,它可以比较、分割和重新计算奇偶校验,而无需接触磁盘,然后稍后刷新它。您创建了一种 md 总是错过缓存的情况,在这种情况下,它必须从磁盘读取条带,比较数据,分割新数据,重新计算奇偶校验,然后将新条带直接刷新到磁盘。缓存命中时需要从磁盘零次读取和写入,现在需要六次读取和六次写入每写一条条纹。
诚然,您观察到的性能差异是巨大的(1.9GB/s 对 449KB/s),但我认为这都是由于 md 为维护数据完整性所做的工作量造成的。
这种性能下降可能会因磁盘的排列方式而加剧……如果将它们全部放在一个控制器上,那么过多的读写操作将导致性能陷入停滞。
答案3
您能告诉我们您的 6 个磁盘是如何组成的吗?在我看来,它们好像是 SAN/DAS 的任何目标的一部分 - 可能由相同的物理磁盘组成(因此,如果所有 6 个磁盘都位于同一个磁盘上,与单个磁盘相比,这将使性能降低 6 个)。
那么您是如何设置位图的?