我们在使用磁盘时,有时希望它更快,但I/O操作很慢,因此可能会称为整个系统的瓶颈。我们在使用磁盘时,有时希望它更大。会有越来越多的数据需要存储,因此磁盘变得越来越满。我们在使用磁盘时,有时希望它更可靠。如果磁盘出现故障,而数据没有备份,那么所有有价值的数据都没有了。
关键问题:如何得到大型、快速、可靠的磁盘
我们如何构建一个大型、快速和可靠的存储系统?关键技术是什么?不同方法之间的折中是什么?
接下来我们将学习独立磁盘冗余阵列(Redundant Array of Independent Disks,RAID),书上原文写的是(Redundant Array of Inexpensive Disks, 廉价冗余磁盘阵列),这是因为早期RAID技术出现的时候,单个高性能且大容量的磁盘价格很昂贵,如果通过多个容量小,价格便宜的磁盘组成大一点的阵列会更加的经济。因此,这里说的廉价并非指硬盘价格本身廉价,而是相对其它高性能磁盘而言是一种更经济的解决方案。
这种技术使用多个磁盘一起构建更快、更大、更可靠的磁盘系统。这个在20世纪80年代后期有U.C.伯克利的一组研究人员引入。大约在这个时候,许多不同的研究人员同时提出使用多个磁盘来构建更好的存储系统的基本思想。
从外部看,RAID看起来像一个大磁盘:一组可以读取或携入的块。在内部,RAID是一个复杂的庞然大物,由多个磁盘、内存(包括易失性和非易失性)以及一个或多个处理器来管理系统。硬件RAID非常像一个计算机系统,专门用于管理一组磁盘。
与单个磁盘相比,RAID具有许多优点。一个好处就是性能。并行使用多个磁盘可以大大加快I/O时间。另一个好处是容量。大型数据集需要大型磁盘。最后,RAID可以提高可靠性。在多个磁盘上传输数据(无RAID技术)会使数据容易受到单个磁盘丢失的影响。通过某种形式的冗余(redundancy),RAID可以容许损失一个磁盘并保持运行,就像没有错误一样。
令人惊讶的是,RAID为使用它们的系统透明地(transparently)提供了这些优势,即RAID对于主机系统看起来就像是一个大磁盘。当然,透明的好处在于它可以简单地用RAID替换磁盘,而不需要更换一行软件。操作系统和客户端引用程序无需修改,就可以继续运行。通过这种方式,透明极大地提高了RAID的可部署性(deployability),使用户和管理员可以使用RAID,而不必担心软件兼容性问题。
我们接下来讨论一些RAID的重要方面。从接口、故障模型开始,然后讨论如何在3个重要的方面评估RAID设计:容量、可靠性和性能。然后我们讨论一些对RAID设计和实现很重要的其他问题。
接口和RAID内部
对于上层的文件系统,RAID看起来像是一个很大的、快速的、并且可靠的磁盘。就像使用单个磁盘一样,他讲自己展现为线性的块数组,每个块都可以由文件系统读取或写入。
当文件系统向RAID发出逻辑I/O请求时,RAID内部必须计算要访问的磁盘(或多个磁盘)以完成请求,然后发出一个或多个物理I/O来执行此操作。这些物理I/O的确切性质取决于RAID级别,我们将在下面讨论。但是举一个简单的例子,考虑一个RAID,它保留每个块的两个副本(每个块都在一个单独的磁盘上)。当写入这种镜像(mirrored)RAID系统时,RAID必须为他发出的每一个逻辑I/O执行两个物理I/O。
RAID系统通常构建为单独的硬件盒(这种是硬件RAID,可以独立于主机运行,如下图),并通过标准连接(例如,SCSI或SATA)接入主机。它包括一个微控制器,运行固件以知道RAID的操作。它还包括非易失性存储器,安全地缓冲写入。他甚至可能包含专用的逻辑电路,来执行奇偶校验计算(在某些RAID级别中非常有用,下面会提到)。在很高的层面上,RAID是一个非常专业的计算机系统:它有一个处理器,内存和磁盘。然而它不是运行应用程序,而是运行专门用于专门操作RAID的软件。
故障模型
要理解RAID并比较不同的方法,我们必须考虑故障模型。RAID旨在检测并从某些类型的磁盘故障中恢复(简单说:可以实现容错和故障恢复)。因此,准确地知道哪些故障对于实现工作设计至关重要。
我们假设第一个故障模型非常简单,并且称为故障-停止(fail-stop)故障模型。在这种模式下,磁盘可以处于两种状态之一:工作状态和故障状态。使用工作状态的磁盘时,所有块都可以读取或写入。相反,当磁盘出现故障时,我们认为它永久丢失。
故障-停止模型的一个关键方面是他关于故障检测的假定。具体来说,当磁盘发生故障时,我们认为这很容易检测到。例如在RAID阵列中,我们假设RAID控制器硬件(或软件)可以立即观察磁盘何时发生故障。
因此,我们暂时不必担心更复杂的“无声”故障,如磁盘损坏。我妈也不必担心在其他磁盘上无法访问单个块(有时称为潜在扇区错误)。稍后我们会考虑这些更复杂的(这些错误现在很常见)磁盘错误。
如何评估RAID
我们很快会看到,构建RAID有多种不同的方法。每种方法都有不同的特点,这值得评估,以便了解它们的优缺点。
具体来说,我们将从3个方面评估每种RAID设计。
- 容量(capacity):在给定一组N个磁盘的情况下,RAID的客户端可用的容量有多少?如果没有冗余,答案显然是N。不同的是,如果有一个系统保存每个块的两个副本,我们将获得N/2的有用容量。不同的方案(例如,基于校验的方案)通常介于两者之间。
- 可靠性(reliability):给定设计允许有多少磁盘故障?根据我们的故障模型,我们只假设整个磁盘可能会故障。在后面(关于数据完整性)的学习中,我们将考虑如何处理更复杂的故障模式。
- 性能(performance):性能有些难以评估,因为它在很大程度上取决于磁盘阵列提供的工作负载。因此,在评估性能之前,我们将首先提出一组应该考虑的典型工作负载。
我们接下来将学习3个重要的RAID设计
- RAID 0级(条带化)
- RAID 1级(镜像)
- RAID 4/5级(基于机构校验的冗余)
这些设计中每一个都被命名为一“级”,源于伯克利的Patterson、Gibson和 Katz的开创性工作研究工作中提出和命名的。他们在1987年发表的论文中介绍了一种新型“冗余磁盘阵列”的存储方案,该方案可以通过多个磁盘组合来提高磁盘I/O性能和数据安全性。为了便于区分不同的RAID阵列设计,他们将不同的RAID方案分为不同的级别,并用数字来表示每个级别的特点和功能。这些级别的定义和命名成为了RAID技术的标准,并在后来的硬件和软件产品中得到广泛应用。
RAID 0级:条带化
第一个RAID级别实际上不是RAID级别,因为没有冗余。但是RAID 0级(即条带化,striping)因其更为人所知,可作为性能和容量的优秀上限,所以值得学习。
我们知道,在操作系统的角度来看磁盘,只能看到一个一个的块,这里我们假设每个块的大小是4KB,最简单的条带形式将如下表所示,在系统的磁盘上将块条带化(stripe),假设此处为4个磁盘阵列
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 |
0 | 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
通过上表,我们应该了解了基本的思想:以轮转方式将磁盘阵列的块分布在磁盘上,这种方法的目的是在对数组的连续块进行请求时,从阵列中获取最大的并行性(如,在一个很大的顺序读取中)。我们将同一行中的块称为条带,因此,上面的块0、1、2和3在相同的条带中。
在这个例子中,我们做了一个简化的假设,在每个磁盘上只有1个块(每个大小是4KB),但是这并不是绝对的,我们其实可以让每两个块(4KB+4KB)放置在一个磁盘上(注意看下表中每个磁盘的第一行和第二行),那么此条带就是由4个大块(或32KB)组成。
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 |
0 | 2 | 4 | 6 |
1 | 3 | 5 | 7 |
8 | 10 | 12 | 14 |
9 | 11 | 13 | 15 |
补充: RAID映射问题
在研究RAID的容量、可靠性和性能特征之前,我们首先提是出一个问题,我们称之为映射问题(the mapping problem)。这个问题出现在所有RAID阵列中。简单地说,给定一个逻辑块来读或写,RAID如何确切地知道要访问哪个物理磁盘和偏移量?
对于这些简单的RAID级别,我们不需要太多复杂计算,就能正确地将逻辑块映射到其物理位置。以上面的第一个条带为例(大块大小=1块=4KB)。在这种情况下,给定逻辑块地址A,RAID可以使用两个简单的公式轻松计算要访问的磁盘和偏移量:
磁盘=A%磁盘数
偏移量=A/磁盘数
请注意,这些都是整数运算(例如,4/3=1而不是1.333333333...)。我我们来看看这些公式如何用于一个简单的例子。假设在上面的第一个RAID中,对块15的请求到达。鉴于有4个磁盘,这意味着我们感兴趣的磁盘是(14%4=2):磁盘2。确切的块计算为(14/4=3):块3。因此,应在第三个磁盘(磁盘2,从0开始)的第四个块(块3,从0开始)处找到块14,该块恰好位于该位置。
你可以考虑如何修改这些公式来支持不同的块大小。尝试一下! 这不太难。块大小
一方面块大小主要影响阵列的性能。例如较小的块大小意味着文件将跨多个磁盘进行条带化,从而可以提高对单个文件的读取和写入的并行性。但是,跨多个磁盘访问块的定位时间会增加,因为整个请求的定位时间有所有驱动器上请求的最大定位时间决定。
另一方面,较大的块大小会让文件内的并行性下降,因此依靠多个并发请求来实现高吞吐量。但是较大的块减少了定位时间。例如,如果一个文件放在一个块中并放置在在单个磁盘上,则访问它时发生的定位时间将只是单个磁盘的定位时间。
因此,确定“最佳”的块大小(大块大小)是很难做到的,因为它需要大量关于提供给磁盘系统的工作负载的知识。对于接下来后续的讨论,我们将假定该数组使用单个块(4KB)的块大小。大多数阵列使用较大的块大小(如64KB),但对于我们下面的学习,确切的块大小无关紧要。因此,简单起见,我们用一个单独的块。
回到RAID 0分析
现在我们来评估RAID 0(条带化)的容量、可靠性和性能。
从容量来看,它是顶级的:给定N个磁盘,条件化提供N个磁盘的有用容量。
从可靠性来看,它也是“顶级”的,即任何磁盘故障都会导致直接数据丢失。
从性能来看,它也是顶级的,通常并行适用所有磁盘来为用户I/O提供服务。
评估RAID性能
在分析RAID性能时,可以考虑两种不同的性能指标。首先是单请求延迟。了解单个I/O请求对RAID的满意度非常有用,因为它可以揭示单个逻辑I/O操作期间可以存在多少并行性。第二个是RAID的稳态吞吐量,即许多并发请求的总带宽。由于RAID常用于高性能环境,因此稳态带宽至关重要,因此将成为我们分析的主要重点。
为了更详细的理解吞吐量,我们继续分析顺序(sequentail)和随机(random)两种工作负载的表现。当然,真正的工作负载不是那么简单,并且往往混合了顺序和类似随机的部分,行为介于两者之间。简单起见,我们只考虑这两种可能性。
我们知道,顺序和随机工作负载的测试表现差异会很大。对于顺序访问,磁盘会以最高效的模式运行,花费很少的时间寻道和旋转等待,大部分时间都是在传输数据。对于随机访问,情况恰恰相反:大部分时间都花在寻道和旋转等待了,传输数据上的时间相对较少。为了在分析中捕捉到这种差异,我们将假设磁盘可以连续工作负载下以
S MB/s
传输数据,并且在随机工作负载下以R MB/s
传输数据。一般来说,S比R大得多。为了理解这种差异,我们来做一个简单的练习,给定磁盘以下特征,计算S和R。假设随机传输测试是10KB,连续传输测试是100MB。
平均寻道时间7ms
平均旋转延迟3ms
磁盘传输速率50MB/s
我们首先计算R(随机工作负载),要得到随机工作负载的表现,我们首先需要得到,它是三个时间之和(即寻道+旋转+传输),前两个条件我们已知了,10KB的传输时间我们目前还没有,因此可以计算得到:
(即10KB传输需要0.195ms)
(这里可以直接计算的原因是硬件厂商KB到MB的换算使用的是1000,而不是1024)
通过计算得到10KB随机传输速率是0.98MB/s,接着我们再来计算一下S(连续工作负载),类似的,我们依旧需要先得到,对于连续传输,我们测试的是100MB,因此我们需要计算100MB的传输时间:
如你所见,S比R大得多,R(随机传输时间)小于1MB/s,几乎是S(顺序传输时间)的50倍。
RAID 1级:镜像
我们接着来学习一下RAID 1级,即镜像。对于镜像系统,数据被复制到两个或更多的磁盘中。当然,一份数据会在多个磁盘上都有副本。通过这样做,我们可以容许磁盘故障。
在一个典型的镜像系统中,我们降价设每个逻辑块,RAID保留两个物理副本。如下表
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 |
0 | 0 | 1 | 1 |
2 | 2 | 3 | 3 |
4 | 4 | 5 | 5 |
6 | 6 | 7 | 7 |
在这个例子中,磁盘0和磁盘1具有相同的内容,而磁盘2和磁盘3也具有相同的内容。数据在镜像对之间条带化。实际上,我们也发现了,有多种不同的方法可以在磁盘上放置块副本。上表中的是常见的安排,有时称为RAID-10(或RAID1+0),因为它使用镜像对(RAID-1),然后在其上使用条带化。另一种常见安排是RAID-01(或RAID0+1),它包含两个大型条带化(RAID-0)阵列,然后是镜像(RAID1)。目前,我们的讨论只是假设上表布局的镜像。
RAID-1 分析
让我们来评估一下RAID-1。
容量
从容量的角度来看,RAID-1价格昂贵。在镜像级别=2的情况下,我们只能获得峰值容量的一半。因此,对于N个磁盘,磁盘的可用容量为N/2。】
RAID一致更新问题
在分析RAID-1之前,让我们先讨论所有磁盘RAID系统都会出现的问题,称为一直更新问题(consistent-update problem)。对于任何在单个逻辑操作期间必须更新多个磁盘的RAID,会出现这个问题。在这里,假设考虑镜像磁盘阵列。
想象一下写入发送到RAID,然后RAID决定它必须写入到两个磁盘,即磁盘0和磁盘1。然后,RAID像磁盘0写入数据,但是在RAID发出请求到磁盘1之前,突然发生了掉电(或系统崩溃)。在这种不幸的情况下,让我们假设对磁盘0的请求已完成(但对磁盘1的请求显然没有完成,因为它从未发出)。
这种不合时宜的掉电,导致现在数据块的两个副本不一致(inconsistent)。磁盘0上的副本是新的,磁盘1的副本是旧的。我们希望两个磁盘的状态都是原子地(atomically)更新,也就是说,两者都应该最终成为新版本或者两者都不是。
解决这个问题的普遍方法是,使用某种预写日志(write-ahead log),在做之前首先记录RAID将要执行的操作(即用某个数据更新两个磁盘)。通过采取这种方法,我们可以确保在发生崩溃时,也能够让磁盘的结果是正确的。通过运行一个恢复(recovery)过程,将所有未完成的事务重新再RAID上执行,我们可以确保两个镜像副本(在RAID-1情况下)同步。
最后一个注意事项:每次写入都在磁盘上记录日志,这个代价昂贵的不行,因此大多数RAID硬件都包含少量非易失性RAM(例如电池有备份的),用于执行此类记录。因此,既提供了一致的更新,又不需要花费高昂的代价,将日志记录到磁盘。
可靠性
从可靠性的角度来看,RAID-1表现不错。它可以容许任何一个磁盘的故障。想象一下,在上表中,磁盘0和磁盘2都出故障了。即使出现这种情况,数据依旧没有丢失!更通俗的说,镜像系统(镜像级别为2)肯定可以容许一个磁盘故障,最多可以容许N/2个磁盘故障,这取决于哪些磁盘故障。在实际中,我们通常不喜欢把这样的事情交给运气。因此,大多数人认为镜像对于处理单个故障是很好的。
性能
从性能的角度来看。如果是读取请求的延迟,它与单个磁盘的延迟相同。所有RAID-1都会读取导向一个副本。但如果是写入,则会有些不同,需要完成两次物理写入。这两个写入是可以并行发生了,因此时间大致等于单次写入的时间。但逻辑写入必须等待两个物理写入完成,所以它遭遇到两个请求中最差的寻道和旋转延迟,因此(平均而言)会比写入单个磁盘略高。
接着我们再分析稳定吞吐量,我们一共需要分析顺序工作负载的读写和随机工作负载的读写,我们先从顺序工作负载开始。顺序写入磁盘时,每个逻辑写入必定会导致两个物理写入。例如,当我们写入逻辑块0时,RAID会在内部将它写入到磁盘0和磁盘1。因此,我们可以得出结论,顺序写入镜像阵列期间获得的最大带宽是,即峰值带宽的一半(其中N是磁盘数量,S是每个磁盘的带宽)。
遗憾的是,我们在顺序读取的过程中获得了完全相同的性能。有人可能认为顺序读取的性能会更好(没错,我也是这么认为的,没理解到书上说的为什么会更差),因为它只需要读取一个数据副本,而不是两个。我们用一个例子来说明为什么这没什么太大的帮助。想象一下,我们需要读取块0,1,2,3,4,5,6 和 7。假设我们将0号块分配给磁盘0,将1分配到磁盘2,将2分配到磁盘1,将3分配到磁盘3。接着我们继续分别向磁盘0,2,1和3发出读取请求4,5,6和7。有人可能会天真的认为,我们正在利用所有磁盘,所以得到了阵列的全部带宽。
但是,要看到的情况并非如此,请考虑单个磁盘接收的请求(例如磁盘0)。首先,它收到块0的请求。然后它收到块4的请求(跳过块2)。实际上,每个磁盘都会收到其它块的请求。然后它会从中摘取它可以提供服务的块。当它一直在自己的磁盘中查找自己是否包含这个块(有可能很多块都不是它可以服务的,它需要跳过),不会为客户提供有用的带宽。因此,每个磁盘只能提供一半的峰值带宽。因此,顺序读取只能获得MB/s的带宽。
随机读取是镜像RAID的最佳案例。在这种情况下,我们可以在所有磁盘上分配读取数据,从而获得完整的可用带宽。因此,对于随机读取,RAID-1提供
N * R MB/s
最后,随机写入也会按照你所预想的方式执行:MB/s。每个逻辑写入必须变成两个物理写入,因此在所有磁盘都将被使用的情况下,客户只会看到可用带宽的一半。尽管对逻辑块X的写入变为对两个不同的物理磁盘的两个并行写入,但是对于小型的请求带宽只能打到我们看到的条带化的一半。我们很快会看到,获得一半的可用带宽实际上相当不错!
RAID 4级:通过奇偶校验节省空间
我们还有一种方式,通过奇偶校验(parity)来保障稳定性的方式。具体的说,需要多添加一块磁盘,这块磁盘就是奇偶校验盘。它可以在条带中单个块出现问题时,将出现问题的块数据进行恢复。
如下有一个例子,这个例子中一共有5块磁盘,采用的是RAID-4系统。对于每一条数据,都有一个奇偶校验块,它不是普通的数据存储块,它所存储的结果是基于其它所有数据块的位亦或运算得出的。对于这个例子来说,下表中奇偶校验块P1具有从块4、5、6和7计算出来之后的冗余信息。
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 | 磁盘4(奇偶校验盘) |
0 | 1 | 2 | 3 | P0 |
4 | 5 | 6 | 7 | P1 |
8 | 9 | 10 | 11 | P2 |
12 | 13 | 14 | 15 | P3 |
奇偶校验是如何计算的
刚刚我们说到,奇偶校验块的内容是通过其它其它几个块的数据进行亦或运算得到的(亦或运算就是比较两个值是否不一致。也就是只有1和0进行相比才会得到true(1^0 = 1))。
奇偶计算是什么?
奇偶计算并不是真正的去做奇偶数的计算,它在计算机领域中只是一个技术名词,奇偶校验是一种简单的错误检测技术,它通过在数据中添加一个奇偶位来监测数据传输过程中的错误。
具体地,奇偶校验会对数据中的所有位进行计数,如果计数结果为偶数,则奇偶校验位设置为0,否则设置为1。在接收端,接收到数据后,会重新计算奇偶校验位,如果计算结果与接收到的奇偶校验位不同,则说明数据传输过程中出现了错误。
在RAID 4中,奇偶校验是通过对所有数据块的位异或运算得出的,而不是真正的进行奇偶数的计算。这个奇偶校验信息可以用来检测和恢复数据块的错误,从而提高数据的可靠性和容错性。
当一个数据盘出现问题时,奇偶校验盘就发挥出作用了。它可以使用奇偶校验信息来恢复丢失的数据。对于下面这个表来说,磁盘4是奇偶校验盘,它的结果来源就是对其它4个盘的数据进行亦或计算得出的(
0x12 ^ 0x34 ^ 0x56 ^ 0x78 = 0x8
),得到的结果就是奇偶校验盘上的奇偶校验字节。当其中一个数据盘出现故障时,我们可以使用奇偶校验盘来恢复丢失的数据。例如,我们假设磁盘0的数据丢失了,那么我们使用磁盘1、磁盘2、磁盘3以及奇偶校验盘的数据进行亦或运算,得到的结果就是磁盘0的数据。即
0x34 ^ 0x56 ^ 0x78 ^ 0x8 = 0x12。
。这样我们就通过奇偶校验信息就恢复了所丢失的数据,再将这个数据恢复到磁盘0中。磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 | 磁盘4(奇偶校验盘) |
0x12 | 0x34 | 0x56 | 0x78 | 0x8 |
ㅤ | ㅤ | ㅤ | ㅤ | ㅤ |
RAID-4 分析
现在让我们来分析一下RAID-4。
容量
从容量的角度来看,RAID-4使用了一个磁盘来冗余每组磁盘的奇偶校验信息。因此最大可用容量是(N-1)。
可靠性
从可靠性的角度来看,RAID-4允许1个磁盘出现故障,同一时间不允许出现更多。如果同一时间多个磁盘出现故障,则无法重建丢失的数据。
性能
关于性能,我们先从稳定吞吐量开始分析。对于连续读取来说,除了奇偶校验盘,其它所有磁盘都是可用的,因此可以提供(N-1)* S MB/s的峰值带宽。
接着是顺序写入,对于顺序写入,我们需要了解顺序写入是如何完成的。将一个很大的数据写入到磁盘时,RAID-4可以执行一种简单优化,称为全条带写入(full-stripe write)。对于一个如下的磁盘,假设我们需要将数据写入到块0、1、2和3中。
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 | 磁盘4(奇偶校验盘) |
0 (0x12) | 1 (0x34) | 2 (0x56) | 3 (0x78) | P0 (0x8) |
4 | 5 | 6 | 7 | P1 |
对于这个例子,即把整个条带上的数据都进行修改,只需要简单重新计算P0的新值(即对块0、1、2和3中的执行亦或),然后将所有块并行的写入到上面5个磁盘中(包含奇偶校验块),因此,全条带写入是RAID-4写入磁盘的最佳方式(即整个条带的数据都发生更新)。
当我们理解全条带写入之后,计算RAID-4的顺序写入就很容易。有效带宽也是(N-1)* S MB/s。即使奇偶校验盘在操作的过程中一直处于忙态,用户也依旧无法获得性能优势。
我们继续分析随机读取,从上表中也很明显,我们依旧可以获得(N-1)* R MB/s的带宽。
最后是随机写入,这是RAID-4中最有意思的部分。想象一下,我们现在只对块1进行了更新,那么块1和奇偶校验块P0也都需要重新更新。那么问题来了:该如何进行更新?
存在两种方法。第一种称为加法奇偶校验(additive parity)。当我们对块1进行更新后,需要并行的读取其它块(本例中是块0、2和3),然后再和块1进行一次新的亦或运算,接着将结果写入到奇偶校验块中。
这个方法有一个问题,在磁盘较多的场景,它需要大量的读取其它磁盘的数据(这个过程会增加耗时)。因此,导致了减法奇偶校验(subtractive parity)方法。
对于减法奇偶校验,也很简单,奇偶校验块会先减去(减法是用亦或运算)旧的值,然后用新的值重新对奇偶校验值进行运算,对于我们这个例子来说,块1的值是0x34,将它先减去,那么只需要(
0x8 ^ 0x34 = 0x3c
)。接着再用新值重新参与运算,我们假设对块1的数据进行亦或预算后得到的是0x58
,那么将它与奇偶校验值进行一次运行0x3c ^ 0x58 = 0x64
得到新的奇偶校验值,因此P0应该被更新成0x64
。更新后的内容如下磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 | 磁盘4(奇偶校验盘) |
0 (0x12) | 1 ( 0x3c ) | 2 (0x56) | 3 (0x78) | P0 ( 0x64 ) |
4 | 5 | 6 | 7 | P1 |
那么,对于RAID-4中的随机写入来说,如果采用减法奇偶校验,每对一个块进行写入,需要读取一次新的块,进行亦或运算,还需要读取一次奇偶校验块,然后进行一次亦或运算,再将新的奇偶校验值写入到奇偶校验块,同时还需要将新的块的内容将老块替换掉,这中间发生了多次的读取了写入(读取新块,读取奇偶校验块,写入新块,写入奇偶校验块)。因此,在RAID-4中的随机写入速度为
R/2 MB/s
。关于
R/2 MB/s
具体是如何计算的,看了书上和chatGPT,没有给出明确的计算公式,大致的意思是所有的写入都会对奇偶校验盘进行写入,如果多个写入并发时,可能会排队。只列举了上述的几个影响因素。如何选择加法奇偶校验或减法奇偶校验
关于该选择加法奇偶校验还是减法奇偶校验,取决于读写操作的比例和并发度,如果RAID4的读取操作比写入操作更频繁,或者写入操作的并发度较低,那么使用加法奇偶校验可以更好地满足RAID4的性能需求。因为在这种情况下,奇偶校验块的更新速度不会对RAID4的性能产生太大的影响,而加法奇偶校验的计算速度更快,可以更好地利用磁盘的带宽,提高RAID4的读写性能。
如果RAID4的写入操作的并发度较高,或者需要提高RAID4的写入性能,那么使用减法奇偶校验可以更好地满足RAID4的性能需求。因为在这种情况下,奇偶校验块的更新速度会变得更加重要,而减法奇偶校验可以减少奇偶校验块的更新次数,提高RAID4的写入性能。
此外,RAID4的磁盘数量也会影响RAID4的性能和可靠性。当RAID4的磁盘数量较少时,使用加法奇偶校验可以更好地利用磁盘的带宽,提高RAID4的读写性能。当RAID4的磁盘数量较多时,使用减法奇偶校验可以更好地提高RAID4的写入性能。但是,磁盘数量的增加也会增加磁盘故障的概率,因此需要更加注意RAID4的数据备份和恢复策略,以保证数据的安全性。
延迟
最后是RAID-4的I/O延迟。对于单次读取,只会映射到单个磁盘,因此其延迟等同于单个磁盘请求的延迟。单次写入的话,需要两次读取,两次写入。读的操作是可以并行的,写入的操作也是(写入数据块和奇偶校验块),因此总延迟大约是单个磁盘的两倍(有一些差异,因为我们必须等待两个读取操作完成,所以会得到最差的定位时间,但是之后,但更新不会导致寻道成本,因此可能是比平均水平更好的定位成本)
RAID-4 最大的问题
RAID-4有一个最为致命的问题,即所有的奇偶校验块都存放在一个磁盘中。这就导致了,如果出现了并发的写请求的话(对这块奇偶校验盘的不同块进行更新),这块奇偶校验盘就会成为性能的瓶颈。
来看一个小例子,假设我们需要对块4,和块13进行写入操作。对这两个块的读取和写入是可以并行执行的,因为它们在两块不同的磁盘。我们知道,在RAID-4中,对一个数据块更新后,同时需要对其对应的奇偶校验块也进行更新。
现在也许你已经猜到了,有两个写入请求在磁盘4上发生了,那么必然就会出现排队阻塞的情况。当写入操作比较多时,这块奇偶校验盘就成了性能的瓶颈。因此我们有时也会将其称为基于奇偶校验的RAID的小写入问题(small-write problem)。
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 | 磁盘4(奇偶校验盘) |
0 | 1 | 2 | 3 | P0 |
4 | 5 | 6 | 7 | P1 |
8 | 9 | 10 | 11 | P2 |
12 | 13 | 14 | 15 | P3 |
这个问题会导致RAID-4的写入表现在有些情况下更为糟糕,且多增加磁盘也无济于事。
RAID-5级:旋转奇偶校验
RAID-5是基于RAID-4的,但是优化与解决了一些问题,其中最为主要的修改就是将奇偶校验块的存储方式进行了修改。在RAID-5中,奇偶校验块分布在所有磁盘上。如下所示,每个条带的奇偶校验块都在磁盘上旋转。这样可以在并发写的时候提升效率。
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 | 磁盘4 |
0 | 1 | 2 | 3 | P0 |
5 | 6 | 7 | P1 | 4 |
10 | 11 | P2 | 8 | 9 |
15 | P3 | 12 | 13 | 14 |
P4 | 16 | 17 | 18 | 19 |
RAID-5分析
RAID-5的大部分分析都和RAID-4一致。容量,可靠性,顺序读写的性能这些都是相同的。单个读写请求的延迟也是相同的。
随机读取的性能会稍微好一点,因为我们可以利用所有的磁盘。
最后,随机写入的性能有明显的提高,因为它允许跨请求进行并行处理。例如对块1和块10进行写入。这会导致磁盘0和磁盘1以及磁盘4和磁盘2(奇偶校验块)发生写入请求。因此,它们可以并行的进行。事实上,我们通常可以假设,如果有大量随机的请求,我们将能保持所有的磁盘都在忙碌。如果是这样的话,那么我们用于小写入的总带宽是 MB/s。四倍的损失是由于每个RAID-5写入仍然能产生总计4个I/O操作(读取新数据块,读取奇偶校验块。写入数据块,写入奇偶校验块),这就是使用基于奇偶校验的RAID的成本。
由于RAID-5基本上与RAID-4相同,且它的性能会比RAID-4更好,所以RAID-5几乎完全取代了市场上的RAID-4。唯一没有取代的地方是系统知道自己绝不会执行大写入以外的任何事情,从而完全避免了小写入问题。在这种情况下,有时会使用RAID-4,因为它的构建会更简单一些。
RAID 总结
我们现在来总结一下各级RAID的比较。请注意,我们省略了一些细节来分析。例如,在镜像系统中写入时,平均查找时间比细入单个磁盘时略高,因为寻道时间是两个寻道时间(每个磁盘一个)的最大值。因此,对连个磁盘的随机写入性能通常会比单个磁盘的随机写入性能稍差。
此外,在RAID-4/5中更新奇偶校验磁盘时,旧奇偶校验的第一次读取可能会导致完全寻道和旋转,但第二次细入奇偶校验只会导致旋转。
ㅤ | RAID-0(条带化) | RAID-1(镜像) | RAID-4(奇偶校验) | RAID-5(旋转奇偶校验) |
容量 | N | N/2 | N-1 | N-1 |
可靠性 | 0 | 1(至少)
N/2(最大情况) | 同一时间1块磁盘 | ㅤ |
吞吐量 | ㅤ | ㅤ | ㅤ | ㅤ |
顺序读 | ||||
顺序写 | ||||
随机读 | ||||
随机写 | ||||
延迟 | ㅤ | ㅤ | ㅤ | ㅤ |
读 | T | T | T | T |
写 | T | T | 2T | 2T |
从上表中我们可以看到基本的差异,对于理解RAID各级之间的这种很有用。对于延迟分析,我们就使用T来表示对单个磁盘的请求所需时间。
总之,如果你严格要求性能,而不关注可靠性的话,那么RAID-0条带化显然是最好的。但是如果你想要随机I/O的性能和可靠性,镜像是最好的,但需要付出的代价是容量下降。如果容量和可靠性都需要的话,那么RAID-5可能比较适合你,付出的代价是小写入时的性能。但是,如果你总是在按顺序执行I/O操作并且希望容量最大化,那么RAID-5也是最匹配的。
其它有趣的RAID问题
还有一些其他有趣的想法,人们可以(并且应该)在讨论RAID时讨论。以下是我们最终可能会写的一些内容。
例如,还有很多其他RAID设计,包括最初分类中的第2和第3级以及第6级可容许多个磁盘故障[C+04]。还有RAID在磁盘发生故障时的功能;有时它会有一个热备用(hotspare)磁盘来替换发生故障的磁盘。发生故障时的性能和重建故障磁盘期间的性能会发生什么变化?还有更真实的故障模型,考虑潜在的扇区错误(laternt sector error)或块损坏(block corruption)[B+08],以及处理这些故障的许多技术(详细信息参见数据完整性章节)。
最后,甚至可以将RAID构建为软件层: 这种软件RAID多系统更便宜,但有其他问题,包括一致更新问题[DAA05]。
其它常见的RAID级别
除了RAID-0、RAID-1、RAID-4和RAID-5,还有一些其他的RAID级别也被广泛使用。以下是一些常见的RAID级别:
RAID-6:RAID-6是在RAID-5的基础上增加了一个奇偶校验块,可以在两个磁盘故障时保证数据的完整性。RAID-6比RAID-5更具有容错能力,但是写操作性能较低。
RAID-10:RAID-10是将RAID-0和RAID-1结合起来的一种RAID级别。RAID-10将多个磁盘分成两组,每组中的磁盘使用RAID-0进行条带化,然后使用RAID-1进行镜像。RAID-10具有较高的性能和容错能力,但是需要使用更多的磁盘。
RAID-50:RAID-50是将RAID-5和RAID-0结合起来的一种RAID级别。RAID-50将多个RAID-5组合成一个RAID-0,可以提高读写操作的性能,同时也具有较高的容错能力。
RAID-60:RAID-60是将RAID-6和RAID-0结合起来的一种RAID级别。RAID-60将多个RAID-6组合成一个RAID-0,可以提高读写操作的性能,同时也具有更高的容错能力。
这些RAID级别都有各自的优缺点,选择哪种RAID级别需要根据具体的应用场景和需求来决定。