软件 RAID 5 和 6 条带大小:为什么越小效率越低?

软件 RAID 5 和 6 条带大小:为什么越小效率越低?

我在这里读到,小条带大小对于 Linux 中的软件(也可能是硬件)RAID 5 和 6 不利。我看到的罕见基准完全同意这一点。
但大家给出的解释是这会引起更多的头部运动。我只是不明白小条纹如何导致更多的头部运动。

假设我们有一个包含 4 个本地 SAS 驱动器的 RAID 6 设置。

情况 1:我们写入 1 Gb 的顺序数据
该程序要求内核写入数据,然后内核将其划分以匹配条带大小并计算要写入每个磁盘的每个块(数据和/或奇偶校验)。
内核能够同时写入 4 个磁盘(使用适当的磁盘控制器)。
如果写入的数据未与条带完全对齐,则内核只需在计算结果数据之前读取第一个和最后一个条带。所有其他条带只会被覆盖,而不关心以前的数据。
由于此计算的完成速度比磁盘吞吐量快得多,因此每个块都会直接写入每个磁盘上前一个块的旁边,而不会暂停。所以这基本上是对 4 个磁盘的顺序写入。
小的条带大小如何减慢速度?

情况 2:我们在随机位置写入 1,000,000 x 1 kb 数据
1 kb 小于条带大小(目前常见的条带大小为 512 kb)
程序要求内核写入一些数据,然后写入其他数据,然后再次写入其他数据,依此类推。对于每次写入,内核都必须读取当前的数据。磁盘上的数据,计算新内容,并将其写回磁盘。然后头部移动到其他地方,并且该操作会重复 999,999 次。
条带大小越小,读取/计算/写入数据的速度越快。理想情况下,4 kb 的条带大小对于现代磁盘来说是最佳的(如果正确对齐)。

那么再一次,小条带大小如何减慢这一速度呢?

答案1

据我所知,这个问题从来都与头部运动无关,而这一切都只是由于更多的开销造成的。对于给定的顺序读取或写入,4KB 条带大小导致的操作比 64KB 条带大小多十六倍。更多的 CPU 时间、更多的内存带宽、更多的上下文切换、更多的 I/O、内核 I/O 调度程序的更多工作、更多的计算合并等等,因此最终每个 I/O 的延迟会更多。

请记住,许多应用程序发出队列深度为 1 的 I/O,因此您可能并不总是能够将 16 个 4KB 顺序请求合并到对磁盘的 64KB 请求。

另外,如果您查看一个典型的 ATTO 磁盘基准测试,如下所示:

在此输入图像描述

您可以看到,磁盘甚至无法全速顺序读取,直到以 128KB 或更大的块完成读取。

Tomshardware 对条带大小的影响进行了相当全面的审查:

http://www.tomshardware.com/reviews/RAID-SCALING-CHARTS,1735.html

答案2

我谈论的是 Linux 软件 RAID。当你看的时候进入代码,您会看到 md 驱动程序未完全优化:当发出多个连续请求时,md 驱动程序不会合并为更大的请求。在某些常见情况下,这会导致巨大的开销。

大的读取或写入被优化:它们被削减为与条带大小相同的几个请求,并得到最佳处理。

如果读取或写入跨越 2 个条带,则 md 驱动程序可以正确完成工作:所有内容都在一个操作中处理。

对于小读取,没有问题,因为第一次读取后数据位于内核缓存中。因此,与缓慢的磁盘带宽相比,多次连续读取只会对 CPU 和内存产生很小的开销。
例如,我一次读取 1 Gb 的数据 100 字节:内核首先会将其转换为 512 kb 读取,因为这是最小 I/O 大小(如果条带大小为 512 kb)。所以接下来的 100 个字节将已经在内核缓存中。这与从非 RAID 分区读取完全相同。

对于小于条带大小的写入,md 驱动程序首先将完整条带读入内存,然后用新数据覆盖内存,然后计算结果(如果使用奇偶校验)(主要是 RAID 5 和 6),然后将其写入磁盘。
例如,我一次写入 1 Gb 的数据 100 字节:内核将首先读取 512 kb 条带,覆盖内存中所需的部分,如果涉及奇偶校验,则计算结果,然后将其写入磁盘。当写入接下来的 100 个字节时,仅避免“读取 512 kb 条带”,因为数据位于内核缓存中。因此,我们在覆盖内存和计算奇偶校验方面的开销很小,但由于数据被再次写入同一条带,所以开销很大。这里的内核代码没有优化。

我没有进行足够的挖掘来理解为什么这些重复写入没有正确缓存,并且数据仅在几秒钟后刷新到磁盘(因此每个条带仅一次)。如果它们被缓存,开销只会是一些 CPU 和内存,但我自己的基准测试显示 CPU 仍然低于 10%,而 I/O 是瓶颈。

如果写入经过优化,则最小条带大小将始终是最佳的:具有 4 个磁盘、4 k 扇区的 RAID 6 将产生 8 kb 条带,并且对于每种可能的负载来说,它将是最佳的读写吞吐量。

答案3

与所有事情一样,有一个折中办法。但我建议您查看一下 RAID2 和 RAID3(这两种类型很少使用),以了解问题的本质。

然而,它基本上可以归结为 IO 和并发数据传输的延迟。每次读取 IO 操作都会有几毫秒的开销,用于磁头寻道和驱动器旋转。

如果我们有更大的数据块,我们支付这种惩罚的频率就会减少。它很像一种更原始​​的预取形式 - 由于这种开销,在请求一个数据块时预取多个数据块通常是一个好主意,因为从统计上看,您无论如何都可能需要它。

但最重要的是——这是一场表演调音操作而不是硬性规则 - 您应该根据发送到磁盘的工作负载来设置块大小。如果您的工作负载是混合的或随机的,那么做到这一点就会变得越来越困难。更大的块意味着更高的吞吐量和更少的 IO 操作,而且通常您的 IO 操作是驱动器速度的限制因素,因此通常有利于提出更大的要求。

对于特定的用例(例如数据库!),这可能不适用。

相关内容