RAID 性能实务
选择 RAID 级别是一项在众多因素之间求取平衡的工作,这些因素包括成本、可靠性、容量,当然还有性能。RAID 性能可能很难理解,尤其是因为不同的 RAID 级别采用不同的技术,在某些情况下彼此的行为相当不同。在本文中,我想探讨常见的 RAID 级别 RAID 0、5、6 和 10,看看它们之间的性能有何差异。
就本文而言,将假定 RAID 1 是 RAID 10 的一个子集。把 RAID 1 这样来理解往往很方便——即把它简单地看作一个只有单一镜像对成员的 RAID 10 阵列。由于 RAID 1 实际上就是一个单对的 RAID 10 并如此行事,这种理解方式对于让 RAID 性能变得易于理解极为有效,因为它直接映射到 RAID 10 的性能曲线之上。
对于所有存储而言,需要审视两类性能:读取和写入。就 RAID 而言,读取极其简单,而写入则相当复杂。读取性能在所有 RAID 类型中实际上是稳定的。然而,写入并非如此。
为了让讨论性能更加容易,我们需要定义几个术语,因为我们将会用到一些公式。在我们的讨论中,我们将用 N 来表示阵列中驱动器(通常称为主轴,spindle)的总数,并用 X 来表示每一块驱动器各自的性能。这使我们能够以驱动器性能的某个倍数的形式来谈论相对性能,从而把 RAID 阵列抽象掉,无需以原始 IOPS 的方式去思考。这一点很重要,因为 IOPS 往往很难界定,但我们可以通过相对于阵列内单块驱动器来阐述,从而以一种有意义的方式来比较性能。
同样重要的是要记住,我们谈论的仅仅是 RAID 阵列本身的性能,而非整个存储子系统的性能。诸如内存缓存和固态缓存之类的因素会对存储子系统的整体性能产生惊人的改变,但它们从根本上并不改变底层 RAID 阵列本身的性能。没有简单的公式可以确定不同的缓存选项将如何影响整体性能,但只需说明这一点便已足够:其影响可能非常显著,但这在很大程度上不仅取决于缓存选择本身,也在很大程度上取决于工作负载。即便是最大、最快、最强健的缓存选项,也无法改变一个阵列长期、持续的性能。
RAID 很复杂,许多因素都会影响最终的性能。其一是 RAID 系统本身的实现。一个糟糕的实现可能会造成延迟,或者可能未能充分利用可用的主轴(比如让一个 RAID 1 阵列只从一块磁盘读取,而不是同时从两块磁盘读取!)。没有简单的办法来计入特定 RAID 实现中的缺陷,因此我们必须假定所有实现都在按规范的极限运作,事实上任何企业级 RAID 系统都会如此。未能做到这一点的,主要是业余爱好者和消费级的 RAID 系统。
某些类型的 RAID 还伴随着大量的计算开销,而另一些则没有。主要是奇偶校验 RAID 级别需要繁重的处理来应对写入操作,不同级别在每次操作上所需的计算量各不相同。这会引入延迟,但不会削减吞吐量。然而,这种延迟会有所不同,取决于该 RAID 级别的实现以及相关系统的处理能力。硬件 RAID 会使用诸如通用 CPU(通常是 Power 或 ARM RISC 处理器)或定制的 ASIC 来处理这件事,而软件 RAID 则把这件事交给服务器自身的 CPU。服务器 CPU 在这里往往实际上更快,但会消耗系统资源。ASIC 可以非常快,但生产成本高昂。这种延迟会影响存储性能,但非常难以预测,并且可能从微不足道到相当显著不等。因此我会在介绍每个 RAID 级别时提及其相对的延迟影响,但不会尝试去测量它。在大多数 RAID 性能计算中,这种延迟会被忽略,但重要的是要理解它的存在,并且根据阵列的配置,它有可能对某个工作负载产生明显的影响。
应当一提的是,由于数据在磁盘本身上布局方式的效率问题,读取操作存在一种微小的性能影响。奇偶校验 RAID 要求磁盘上存在一些数据,这些数据在健康的读取操作期间毫无用处,却又无法被用来加速读取。这实际上导致它略微变慢。但这种影响小得离谱,通常不予测量,因此可以忽略。
诸如条带大小(stripe size)之类的因素当然也会影响性能,但由于那是可配置的,并非任何 RAID 级别中的固有产物,我在此将忽略它。它不是在选择 RAID 级别本身时的一个因素,而仅仅是在选定之后配置某个 RAID 级别时的因素。
我想提及的最后一个因素是存储操作的读写比例。有些 RAID 阵列将几乎纯粹用于读取操作,有些几乎全然用于写入操作,但大多数会使用两者的混合,很可能类似于百分之八十读取、百分之二十写入。这一比例对于理解你将从你特定的 RAID 阵列中获得的性能、以及理解每个 RAID 级别将如何影响你而言,都非常重要。我把它称为读写混合(read/write blend)。
我们主要用 IOPS 来衡量存储性能。IOPS 代表每秒输入/输出操作数(Input/Output Operations Per Second,是的,我知道这些字母对应得不太整齐,但事情就是这样)。我进一步使用术语 RIOPS 表示读取 IOPS,WIOPS 表示写入 IOPS,BIOPS 表示混合 IOPS,混合 IOPS 会带有一个比例,如 80/20 或其他什么比例。许多人用单一的 IOPS 数字来谈论存储性能。当这样做时,他们通常指的是 50/50 的混合 IOPS。然而,几乎没有任何工作负载会以 50/50 的比例运行,因此那个数字可能极具误导性。需要两个数字,即 RIOPS 和 WIOPS,才能理解性能,而这两者结合起来可以用于求出所需的任何 IOPS 混合值。例如,一个 50/50 的混合就简单地是 (RIOPS * .5) + (WIOPS * .5)。更常见的 80/20 混合则是 (RIOPS * .8) + (WIOPS * .2)。
既然我们已经确立了一些标准和背景理解,我们就将深入探讨各个 RAID 级别本身,看看性能在它们之间如何变化。
对于所有 RAID 级别,读取 IOPS 的数字都是用 NX 计算的。当然,这没有计入我上面提及的那些微不足道的开销数字。这是一个“最佳情况”的数字,但现实世界中的数字与之如此接近,以至于直接使用这个公式非常实用。即取主轴数(N)乘以单块驱动器的 IOPS 性能(X)。请记住,驱动器往往具有不同的读取和写入性能,因此务必在读取 IOPS 计算中使用驱动器的读取 IOPS 额定值或实测速度,在写入 IOPS 计算中使用写入 IOPS 速率或实测速度。
RAID 0
RAID 0 是最容易理解的 RAID 级别,因为它实际上没有需要担心的开销,没有为驱动它而消耗的资源,而且读取和写入在任何时候都能充分获益于每一块主轴。因此对于 RAID 0,我们的写入性能公式非常简单:NX。RAID 0 始终是性能最高的 RAID 级别。
一个例子是一个八主轴的 RAID 0 阵列。如果阵列中单块驱动器提供 125 IOPS,那么我们的计算将由 N = 8 和 X = 125 得出,即 8 * 125,得到 1,000 IOPS。由于这里读取和写入 IOPS 相同,所以极其简单,因为我们得到 1K RIOPS、1K WIOPS,以及任何混合比例下的 1K。非常简单。如果我们不知道单块主轴的绝对 IOPS,我们可以把一个八主轴的 RAID 0 称为提供 8X 混合 IOPS。
RAID 10
RAID 10 是计算起来第二简单的 RAID 级别。因为 RAID 10 是镜像组的 RAID 0 条带,我们无需为条带操心任何开销,但每个镜像都必须把相同的数据写入两次才能创建镜像。与同样驱动器数量的 RAID 0 阵列相比,这把我们的写入性能削减了一半。这就给了我们一个简单的写入性能公式:NX/2 或 .5NX。
应当指出的是,在相同容量(而非相同主轴数量)的条件下,RAID 10 拥有与 RAID 0 相同的写入性能,但读取性能是其两倍——这仅仅是因为它需要两倍之多的主轴才能匹配相同的容量。
因此,一个八主轴的 RAID 10 阵列将是 N = 8 和 X = 125,我们得出的计算结果是 (8 * 125)/2,即 500 WIOPS 或 4X WIOPS。一个 50/50 的混合将得出 750 混合 IOPS(1,000 读取 IOPS 和 500 写入 IOPS)。
这个公式同样适用于 RAID 1、RAID 10、RAID 100 和 RAID 01。
诸如 RAID 10 中三重镜像这类不常见的选项会改变这一写入惩罚。例如,采用三重镜像的 RAID 10 将是 NX/3。
RAID 5
虽然 RAID 5 已被弃用,绝不应在新阵列中使用,但我在此将它纳入进来,因为它是一个广为人知且被普遍使用的 RAID 级别,其性能需要被理解。RAID 5 是现代奇偶校验 RAID 级别中最基础的一个。RAID 2、3 和 4 在生产系统中已不再出现,因此我们在此不会探究它们的性能。RAID 5 虽然在今天不推荐使用,却是其他现代奇偶校验 RAID 级别的基础,因此理解它很重要。
奇偶校验 RAID 增加了一项有些复杂的需求,即对于每一次写入磁盘的操作都要校验并重新写入奇偶校验值。这意味着一个 RAID 5 阵列将不得不读取数据、读取奇偶校验、写入数据,最后写入奇偶校验。每一次有效操作要对应四次操作。这给了我们 RAID 5 上为四的写入惩罚。因此 RAID 5 写入性能的公式是 NX/4。
因此,沿用八主轴的例子,其中单块主轴的写入 IOPS 为 125,我们将得到如下计算:(8 * 125)/4,即 2X 写入 IOPS,结果为 250 WIOPS。在一个 50/50 的混合中,这将得出 625 混合 IOPS。
RAID 6
RAID 6 继 RAID 10 之后,大概是当今使用中最常见、最有用的 RAID 级别。然而,RAID 6 是基于 RAID 5 的,并多了一层奇偶校验。这使它比 RAID 5 显著更安全,这一点非常重要,但也带来了一项显著的写入惩罚,因为每一次写入操作都要求磁盘读取数据、读取第一奇偶校验、读取第二奇偶校验、写入数据、写入第一奇偶校验,然后最后写入第二奇偶校验。这算下来是六倍的写入惩罚,相当显著。所以我们的公式是 NX/6。
继续我们的例子,我们得到 (8 * 125)/6,结果约为 167 写入 IOPS 或 1.33X。在我们 50/50 的混合例子中,这是 583.5 混合 IOPS 的性能。如你所见,奇偶校验写入会导致写入性能非常迅速地下降,以及混合性能的明显下滑。
RAID 7(又称 RAID 5.3 或 RAID 7.3)
RAID 7 是一种有些非标准的 RAID 级别,它具有三重奇偶校验,建立在 RAID 5 既有的单奇偶校验和 RAID 6 既有的双奇偶校验之上。RAID 7 目前唯一的实现是 ZFS 的 RAIDZ3。由于 RAID 7 包含了 RAID 5 和 RAID 6 两者的全部开销,再加上第三个奇偶校验组件的额外开销,我们便有了一个惊人的八倍写入惩罚。因此我们求 RAID 7 写入性能的公式是 NX/8。
在我们的例子中,这将意味着 (8 * 125)/8 结果为 125 写入 IOPS 或 1X。所以在我们这个有八块驱动器的阵列中,我们将只能得到一块独立驱动器的写入性能。那是相当可观的开销。我们 50/50 的混合 IOPS 将只得出 562.5。
复杂 RAID
诸如 RAID 50、60、61、16 等复杂 RAID 级别或嵌套 RAID 级别,可以利用上述信息,把该 RAID 分解为它的各个组成部分,并使用上面提供的公式逐一加以应用来求得。这些级别没有简单的公式,因为它们的配置各不相同。有必要把它们分解为各个组成部分,并多次应用这些公式。
对于有十二块驱动器、分为两组各六块驱动器、每块驱动器为 150 IOPS 的 RAID 60,将用两个 RAID 6 来完成。它将是 RAID 0 的 NX,其中 N 为二(对应两个 RAID 6 阵列),而 X 为每个 RAID 6 的结果性能。每个 RAID 6 组将是 (6 * 150)/6。因此整个阵列将是 2((6 * 150)/6),结果为 300 写入 IOPS。
与上面相同的例子,但配置为 RAID 61(即一对镜像的 RAID 6 阵列),每个 RAID 6 阵列的性能相同,但应用于 RAID 1 的公式 NX/2(其中 X 为每个 RAID 阵列的结果性能)。因此最终的公式将是 2((6 * 150)/6)/2,由十二块驱动器得出 150 写入 IOPS。
作为容量函数的性能
当我们推导 RAID 性能公式时,我们是以主轴数量来思考这些公式的,这无比合理。这在确定一个拟建阵列、甚至一个无法测量的现有阵列的性能时非常有用,并使我们能够比较不同拟选方案之间的相对性能。我们普遍都是以这些术语来思考 RAID 性能的。
然而,这并不总是一种好的方法,因为我们通常是把 RAID 作为容量的函数、而非性能或主轴数量的函数来看待的。有人会去考量一个八驱动器的 RAID 6 阵列对比一个八驱动器的 RAID 10 阵列,这虽属可能,但会非常罕见。偶尔由于机箱限制或某种其他类似原因,这种情况会发生。但 RAID 阵列通常是从阵列总容量(例如可用容量)的角度来看待的,而非从主轴数量、性能或任何其他因素来看待。因此,奇怪的是,我们随后竟应当转而把 RAID 性能作为主轴数量的函数来看待。
如果我们改变视角,以容量作为共同因素来作为支点,同时仍假定单块驱动器的容量和性能(X)在各比较对象之间保持恒定,那么我们就会得出一幅截然不同的性能图景。在这样做时我们会看到,例如,RAID 0 不再是性能最高的 RAID 级别,而读取性能则会发生剧烈变化,而不是保持为一个常量。
容量是个变化无常的东西,但我们可以把它提炼为达到所需容量所必需的主轴数量。这使这一讨论容易得多。因此我们的第一步是确定达到原始容量所需的主轴数。例如,如果我们需要 10TB 的容量并使用 1TB 的驱动器,我们就需要十块主轴。或者,如果我们需要 3.2TB 并使用 600GB 的驱动器,我们就需要六块主轴。与之前不同,我们将把我们的主轴数称为 R。与之前一样,单块驱动器的性能表示为 X。(此处使用 R 来表示这是原始容量计数,Raw Capacity Count,而非主轴总数 Number。)
RAID 0 依然简单,性能仍为 RX,因为没有额外的驱动器。读取和写入 IOPS 都简单地是 NX。
RAID 10 拥有 RX 写入 IOPS,但拥有 2RX 读取 IOPS。这相当显著。突然之间,当把性能作为稳定容量的函数来看待时,我们发现 RAID 10 拥有比 RAID 0 两倍的读取性能!
RAID 5 变得稍微更棘手一些。写入 IOPS 将表示为 ((R + 1) * X)/4。读取 IOPS 表示为 ((R + 1) * X)。
RAID 6 正如我们所料,遵循 RAID 5 所投射的模式。RAID 6 的写入 IOPS 为 ((R + 2) * X)/6。而读取 IOPS 表示为 ((R + 2) * X)。
RAID 7 也完全合乎规律。RAID 7 的写入 IOPS 将为 ((R + 3) * X)/8。而读取 IOPS 为 ((R + 3) * X)。
这一视角改变了我们思考性能的方式,而且,当纯粹审视读取性能时,RAID 0 变成了最慢的 RAID 级别而非最快的,而 RAID 10 则成为读取和写入两方面都最快的级别,无论 R 和 X 的取值如何!
如果我们取一个现实世界的例子:用 10 块 2TB 驱动器达到 20TB 的可用容量,每块驱动器拥有 100 IOPS 的性能,并假定为 50/50 的混合,那么得出的 IOPS 将是:RAID 0 为 1,000 混合 IOPS,RAID 10 为 1,500 混合 IOPS(2,000 RIOPS / 1,000 WIOPS),RAID 5 为 687.5 混合 IOPS(1,100 RIOPS / 275 WIOPS),RAID 6 为 700 混合 IOPS(1,200 RIOPS / 200 WIOPS),最后 RAID 7 为 731.25 混合 IOPS(1,300 RIOPS / 162.5 WIOPS)。RAID 10 在这里是大获全胜的赢家。
软件 RAID 的延迟与系统影响
正如我先前所述,RAID 0 和 RAID 10 实际上没有需要考量的系统开销。镜像操作基本上不需要任何计算努力,并且无论从哪个角度看都小到无法测量。奇偶校验 RAID 确实有计算开销,这会导致存储层的延迟以及系统资源被消耗。当然,如果我们使用硬件 RAID,那些资源是专用于 RAID 阵列的,除了在这一角色中被消耗之外别无他用。然而,如果我们使用软件 RAID,这些就是为 RAID 阵列处理目的而被消耗的通用系统资源(主要是 CPU)。
即便对于一个配有大量 RAID 的非常小的系统,其影响仍然非常小,但它可以被测量,并且应当被考虑,哪怕只是略加考虑。延迟和系统影响彼此直接相关。
除了用这种方式之外,没有简单的办法来表述不同 RAID 级别的延迟和系统影响:RAID 0 和 RAID 10 实际上没有延迟或影响,RAID 5 有一些延迟和影响,RAID 6 的计算延迟和影响大约是 RAID 5 的两倍,而 RAID 7 的计算延迟和影响大约是 RAID 5 的三倍。
在许多情况下,这种延迟和系统影响会小到无法用标准的系统工具测量,而且随着现代处理器变得越来越强大,延迟和系统影响将继续减小。自大约 2001 年以来,即便在低端的、商用的硬件上,RAID 5 和 RAID 6 系统的影响也已被认为可以忽略不计。但在负载很重、奇偶校验 RAID 活动量很大的系统上,RAID 子系统与其他需要系统资源的进程之间有可能出现争用。
参考:The IT Hollow – Understanding the RAID Penalty
本文最初发布于 StorageCraft 博客 – RAID Performance。
