我在这里读到,小条带大小对于 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 的条带大小对于现代磁盘来说是最佳的(如果正确对齐)。
那么再一次,小条带大小如何减慢这一速度呢?
我谈论的是 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 条带,并且对于每种可能的负载来说,它将是最佳的读写吞吐量。