![Linux软件raid1:哪些原因可能导致读取速度降低?](https://linux22.com/image/188207/Linux%E8%BD%AF%E4%BB%B6raid1%EF%BC%9A%E5%93%AA%E4%BA%9B%E5%8E%9F%E5%9B%A0%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E8%AF%BB%E5%8F%96%E9%80%9F%E5%BA%A6%E9%99%8D%E4%BD%8E%EF%BC%9F.png)
将两个 PCIe NVMe SSD 配置为 raid1 Linux 软件 raid 而不是提高读取性能,因此读取速度大约减半。
在类似的 Linux 软件 raid1 设置(还有 SSD)中,我发现读取性能有所提高,因为现在可以使用两个镜像块设备进行读取。
解决此性能问题的潜在原因和调查路线可能是什么?
基准测试是使用fio
read with 4k on /dev/md125
(the raid1)/dev/nvme1n1
及其/dev/nvme0n1
成员完成的。从它们读取比从 读取更快/dev/md125
。
似乎其他使用 Linux raid1 软件的人也面临着违反直觉的速度降低,而不是通过 raid1 读取获得速度增益(请参阅https://serverfault.com/questions/235199/poor-software-raid10-read-performance-on-linux)。
/dev/nvme1n1p1
以下是使用 fio 在并发和/dev/nvme0n1p1
设备上进行随机 4k 读取的一些性能基准测试数据:
fio4k /dev/nvme1n1p1
[...]
read: IOPS=637k, BW=2487MiB/s (2608MB/s)(146GiB/60001msec)
fio4k /dev/nvme0n1p1
read: IOPS=652k, BW=2545MiB/s (2669MB/s)(149GiB/60001msec)
/dev/md125
如果我生成一个带有两者的raid1 ( /dev/nvme1n1p1
,,/dev/nvme0n1p1
甚至跳过位图以免造成任何负面影响)
mdadm --verbose --create /dev/md/raid1_nvmes --bitmap=none --assume-clean --level=1 --raid-devices=2 /dev/nvme0n1p1 /dev/nvme1n1p1
fio4k /dev/md125
[...]
read: IOPS=337k, BW=1317MiB/s (1381MB/s)(77.2GiB/60001msec)
更新fio
命令行和其他信息
这是使用的 fio 命令(变量BLOCKDEVICE
和BLOCKSIZE
根据上面提供的值进行设置,BLOCKSIZE=4k
BLOCKDEVICE是/dev/nvme0n1p1
和/dev/nvme1n1p1
/dev/md/raid1_nvmes
fio --filename="$BLOCKDEVICE" \
--direct=1 \
--rw=randread \
--readonly \
--bs="$BLOCKSIZE" \
--ioengine=libaio \
--iodepth=256 \
--runtime=60 \
--numjobs=4 \
--time_based \
--group_reporting \
--name=iops-test-job \
--direct=1 \
--eta-newline=1 2>&1
这是我运行的 fio 测试的输出:
测试 fio benchmark 直接块设备/dev/nvme0n1p1
root@ada:/virtualization/machines# cat /usr/local/bin/nn_scripts/nn_fio
#!/bin/bash
set -x
BLOCKDEVICE="$1"
test -b "$BLOCKDEVICE" || { echo "usage: $0 <blockdev> [size_of_io_chunk] [mode: randread]" >&2; exit 1; }
BLOCKSIZE="$2"
test "${BLOCKSIZE%%[kMGT]}" -eq "${BLOCKSIZE%%[kMGT]}" 2>/dev/null || { echo "Run FIO benchmark with block size of 4k"; BLOCKSIZE=4k; }
fio --filename="$BLOCKDEVICE" \
--direct=1 \
--rw=randread \
--readonly \
--bs="$BLOCKSIZE" \
--ioengine=libaio \
--iodepth=256 \
--runtime=60 \
--numjobs=4 \
--time_based \
--group_reporting \
--name=iops-test-job \
--direct=1 \
--eta-newline=1 2>&1 | tee /root/fio.logs/fio.$(basename "$BLOCKDEVICE:").$BLOCKSIZE.$(date -Iseconds)
root@ada:/virtualization/machines# time /usr/local/bin/nn_scripts/nn_fio /dev/nvme0n1p1 [125/294]
+ BLOCKDEVICE=/dev/nvme0n1p1
+ test -b /dev/nvme0n1p1
+ BLOCKSIZE=
+ test '' -eq ''
+ echo 'Run FIO benchmark with block size of 4k'
Run FIO benchmark with block size of 4k
+ BLOCKSIZE=4k
+ fio --filename=/dev/nvme0n1p1 --direct=1 --rw=randread --readonly --bs=4k --ioengine=libaio --iodepth=256 --runtime=60 --numjobs=4 --time_based --grou
p_reporting --name=iops-test-job --direct=1 --eta-newline=1
++ basename /dev/nvme0n1p1:
++ date -Iseconds
+ tee /root/fio.logs/fio.nvme0n1p1:.4k.2021-02-26T11:41:03+01:00
tee: '/root/fio.logs/fio.nvme0n1p1:.4k.2021-02-26T11:41:03+01:00': No such file or directory
iops-test-job: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=256
...
fio-3.12
Starting 4 processes
iops-test-job: (groupid=0, jobs=4): err= 0: pid=28221: Fri Feb 26 11:42:04 2021
read: IOPS=626k, BW=2446MiB/s (2565MB/s)(143GiB/60001msec)
slat (usec): min=2, max=625, avg= 4.59, stdev= 3.06
clat (usec): min=90, max=10696, avg=1629.07, stdev=128.82
lat (usec): min=96, max=10700, avg=1633.79, stdev=129.08
clat percentiles (usec):
| 1.00th=[ 1401], 5.00th=[ 1434], 10.00th=[ 1450], 20.00th=[ 1516],
| 30.00th=[ 1582], 40.00th=[ 1614], 50.00th=[ 1647], 60.00th=[ 1663],
| 70.00th=[ 1696], 80.00th=[ 1729], 90.00th=[ 1762], 95.00th=[ 1811],
| 99.00th=[ 1909], 99.50th=[ 1975], 99.90th=[ 2245], 99.95th=[ 2606],
| 99.99th=[ 3458]
bw ( KiB/s): min=479040, max=691888, per=25.00%, avg=626199.33, stdev=37403.47, samples=477
iops : min=119760, max=172972, avg=156549.78, stdev=9350.91, samples=477
lat (usec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2=99.63%, 4=0.36%, 10=0.01%, 20=0.01%
cpu : usr=30.55%, sys=69.28%, ctx=38473, majf=0, minf=6433
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
issued rwts: total=37573862,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=256
Run status group 0 (all jobs):
READ: bw=2446MiB/s (2565MB/s), 2446MiB/s-2446MiB/s (2565MB/s-2565MB/s), io=143GiB (154GB), run=60001-60001msec
Disk stats (read/write):
nvme0n1: ios=37487591/1001, merge=14/185, ticks=15999825/331, in_queue=24175124, util=100.00%
real 1m0.698s
user 1m20.593s
sys 2m46.774s
在 raid1 上测试 fio 基准/dev/nvme1n1p1
root@ada:/virtualization/machines# time /usr/local/bin/nn_scripts/nn_fio "$(realpath "/dev/md/ada:raid1_nvmes")" [10/330]
+ BLOCKDEVICE=/dev/md127
+ test -b /dev/md127
+ BLOCKSIZE=
+ test '' -eq ''
+ echo 'Run FIO benchmark with block size of 4k'
Run FIO benchmark with block size of 4k
+ BLOCKSIZE=4k
+ fio --filename=/dev/md127 --direct=1 --rw=randread --readonly --bs=4k --ioengine=libaio --iodepth=256 --runtime=60 --numjobs=4 --time_based --group_re
porting --name=iops-test-job --direct=1 --eta-newline=1
++ basename /dev/md127:
++ date -Iseconds
+ tee /root/fio.logs/fio.md127:.4k.2021-02-26T11:49:06+01:00
tee: '/root/fio.logs/fio.md127:.4k.2021-02-26T11:49:06+01:00': No such file or directory
iops-test-job: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=256
...
fio-3.12
Starting 4 processes
iops-test-job: (groupid=0, jobs=4): err= 0: pid=67832: Fri Feb 26 11:50:07 2021
read: IOPS=322k, BW=1257MiB/s (1318MB/s)(73.6GiB/60001msec)
slat (usec): min=3, max=535, avg=10.44, stdev= 5.29
clat (usec): min=47, max=14172, avg=3170.20, stdev=142.99
lat (usec): min=59, max=14179, avg=3180.78, stdev=143.44
clat percentiles (usec):
| 1.00th=[ 2900], 5.00th=[ 2966], 10.00th=[ 2999], 20.00th=[ 3032],
| 30.00th=[ 3097], 40.00th=[ 3163], 50.00th=[ 3195], 60.00th=[ 3228],
| 70.00th=[ 3261], 80.00th=[ 3294], 90.00th=[ 3326], 95.00th=[ 3359],
| 99.00th=[ 3425], 99.50th=[ 3458], 99.90th=[ 3621], 99.95th=[ 3818],
| 99.99th=[ 5866]
bw ( KiB/s): min=293472, max=350408, per=24.99%, avg=321583.77, stdev=11302.31, samples=477
iops : min=73368, max=87602, avg=80395.91, stdev=2825.56, samples=477
lat (usec) : 50=0.01%, 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%
lat (usec) : 1000=0.01%
lat (msec) : 2=0.01%, 4=99.96%, 10=0.03%, 20=0.01%
cpu : usr=18.54%, sys=81.47%, ctx=342, majf=0, minf=11008
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
issued rwts: total=19303258,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=256
Run status group 0 (all jobs):
READ: bw=1257MiB/s (1318MB/s), 1257MiB/s-1257MiB/s (1318MB/s-1318MB/s), io=73.6GiB (79.1GB), run=60001-60001msec
Linux内核版本是:
root@ada:/virtualization/machines# uname -a
Linux ada 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64 GNU/Linux
nvmes 上使用的调度程序是none
:
root@ada:/virtualization/machines# grep . /sys/block/{md127,nvme0n1,nvme1n1}/queue/scheduler
/sys/block/md127/queue/scheduler:none
/sys/block/nvme0n1/queue/scheduler:[none] mq-deadline
/sys/block/nvme1n1/queue/scheduler:[none] mq-deadline
有人请求提供iostat
以下情况的输出:a) 直接 nvme ssd 性能和 b) nvme ssd 的 raid1 性能。
a) 直接NVME性能
tps kB_read/s kB_wrtn/s kB_read kB_wrtn Device
543201.33 2.1G 1.5M 6.2G 4.6M nvme1n1
20.67 1.3k 1.5M 4.0k 4.6M nvme0n1
25.67 1.3k 1.5M 4.0k 4.6M md127
b) raid1 的性能
tps kB_read/s kB_wrtn/s kB_read kB_wrtn Device
169797.33 663.3M 32.3k 1.9G 97.0k nvme1n1
159573.67 623.3M 32.3k 1.8G 97.0k nvme0n1
329367.33 1.3G 32.0k 3.8G 96.0k md127
c) 并行fio基准测试的性能/dev/nvme1n1p1
和/dev/nvme0n1p1
tps kB_read/s kB_wrtn/s kB_read kB_wrtn Device [0/747]
585589.67 2.2G 20.7M 6.7G 62.0M nvme1n1
405723.00 1.5G 20.7M 4.6G 62.0M nvme0n1
421.67 1.1M 20.7M 3.4M 62.0M md127
涉及的两个 NVME 设备是 Samsung Evo 970
root@ada:/sys/module# nvme list
Node SN Model Namespace Usage Format FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 S4EWNM0NC28151E Samsung SSD 970 EVO Plus 1TB 1 284.89 GB / 1.00 TB 512 B + 0 B 2B2QEXM7
/dev/nvme1n1 S4EWNM0NC28144V Samsung SSD 970 EVO Plus 1TB 1 284.89 GB / 1.00 TB 512 B + 0 B 2B2QEXM7
r
它们使用以下方式插入到系统的 PCIe 插槽中这个适配器。 lspci 的输出是:
root@ada:/sys/module# lspci -vv | grep -i 'nvme ssd controller'
41:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981 (prog-if 02 [NVM Express])
Subsystem: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981
62:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981 (prog-if 02 [NVM Express])
Subsystem: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981
该系统是一个 DELL 服务器系统,具有 512GiB 内存和两个配备 AMD EPYC 7551 32 核处理器的插槽。
在基准测试期间没有出现任何dmesg
错误。
答案1
(对于那些发布涉及 的问题fio
,我强烈建议您清楚地发布您正在运行的完整作业和 fio 版本号因为这些事情会对你是否得到问题的正确答案产生巨大的影响)
fio
正在报告 mdadm 情况下的更多内核开销,并检查作业上下文切换次数的差异。您可能想考虑让 fio 进行批处理 -https://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-iodepth-batch-submit——所以每次调用都可以一次性提交更多内容。此外,/dev/md/raid1_nvmes
如果 fio 无法使用之前的命令行提供磁盘统计信息,您可能希望将其用作 RAID 设备名称。
另一件需要检查的事情是同时从两个底层磁盘读取时获得的速度。一个示例工作是这样的:
fio --direct=1 --rw=randread --readonly --bs=4k --ioengine=libaio \
--iodepth=1024 --runtime=60 --time_based \
--name=solo1 --filename=/dev/nvme0n1p1 --stonewall \
--name=solo2 --filename=/dev/nvme0n1p1 --stonewall \
--name=duo1 --filename=/dev/nvme0n1p1 --name=duo2 --filename=/dev/nvme1n1p1
希望solo
作业能够自行运行并且duo
作业同时运行,但我的 fio 作业格式可能有点生疏,因此请随意使用它或将二重奏运行分成单独的 fio 调用。
死胡同的想法
遗憾的是,mdadm RAID 块大小的概念与这个特定问题没有任何关系。与 RAID 0/4/5/6/10 不同,mdadm 的 RAID 1 没有块(请参阅此回答 mdadm raid1 以及 4k 驱动器上的块大小(或块大小)是多少?--chunk
或在中搜索mdadm 手册页)。
如果您正在执行的 I/O 是单个顺序流,预计不会mdadm RAID1读取速度应该比单个磁盘的读取速度快。如上所述,这不应该适用于这种情况,因为 a) 读取是随机的 b)numjobs
发生了多个并行读取器(在 fio 情况下通过)。