RAID:原理与计算
独立硬盘冗余阵列(RAID, Redundant Array of Independent Disks),旧称廉价磁盘冗余阵列(Redundant Array of Inexpensive Disks),简称磁盘阵列。利用虚拟化存储技术把多个硬盘组合起来,成为一个或多个硬盘阵列组,目的为提升性能或减少冗余,或是两者同时提升。
RAID技术使用多个磁盘构建了一个更快、更大、更可靠的磁盘系统。在外部看来,RAID就是一个磁盘,而在内部,RAID所组成的系统则十分复杂,由多个磁盘、内存(包括易失性和非易失性内存)以及一个或多个处理器来管理。
与使用单个磁盘相比,RAID具有以下优点:
- 性能更好。通过并行使用多个磁盘,可以大大加快IO时间。
- 可靠性更好。RAID通过某种形式的数据冗余,可以最大程度减轻数据错误的情况。
- 容量更大。显然,采用多个磁盘使得RAID的容量更大了。
本文我们主要探讨一些主要的RAID技术原理,并通过实际计算加深对RAID的理解。
数据分条
我们想要通过并行访问硬盘来提高数据的访问速度,就必须将数据分散到各个磁盘中。而拆分数据最简单的形式就是数据分条(data striping),所谓的分条,你可以想象为将一连串的数据(可以是连续的比特或者连续的数据块)切分成一段一段的数据条。
其中一种数据分条的方式是位级分条(bit-level striping)。假设我们有8块磁盘,编号0到7,那么就可以将每一个字节的第i位(i的范围也是0到7)写入到磁盘i上。这样我们就能将8块磁盘当做1块磁盘使用,同时获得8倍的速度提升。这种方式可以推广至任意2的幂次块磁盘上,例如有4块磁盘,那么只需将第i和第i+4位存储在磁盘i上即可。
另一种方式是块级分条(block-level striping),文件的块可能分散在多个磁盘上。除此之外,实际上还存在其他分条级别,比如按照单个山区或者单块扇区分条,但块级分条是最常见的。
下表总结了各RAID级别的分条方式。
位级分条 | 块级分条 |
---|---|
RAID2、RAID3 | RAID0、RAID1、RAID4、RAID5 |
标准RAID
RAID0:条带化
RAID0严格意义上来说不能算是RAID,因为它不存在冗余。RAID0只是简单的将所有磁盘并联起来,所有的数据块级分条,以条带化(stripe)的方式存储。
假设我们有4个磁盘,12个数据块,那么数据块将按照以下方式存储于RAID0系统中。
磁盘0 | 磁盘1 | 磁盘2 | 磁盘3 |
---|---|---|---|
0号块 | 1号块 | 2号块 | 3号块 |
4号块 | 5号块 | 6号块 | 7号块 |
8号块 | 9号块 | 10号块 | 11号块 |
上表中的每一行称为条带(比如第一行的0、1、2、3号块)。当我们要请求连续的一组数据时(比如访问数组),就能够充分利用磁盘阵列的并行性。因为读写时都可以并行处理,所以在所有的级别中,RAID 0的速度是最快的。但是RAID 0既没有冗余功能,也不具备容错能力,如果一个磁盘(物理)损坏,所有数据都会丢失。
RAID1:镜像
RAID1将磁盘分为两组,它们互相作为另一组的镜像。只要一个磁盘正常即可维持运作,可靠性最高。其原理为在主硬盘上存放数据的同时也在镜像硬盘上写一样的数据。当主硬盘(物理)损坏时,镜像硬盘则代替主硬盘的工作。因为有镜像硬盘做数据备份,所以RAID1的数据安全性在所有的RAID级别上来说是最好的。但由于利用率只有一半,所以RAID1在所有的RAID级别中利用率是最低的。
如果用两个不同大小的磁盘建RAID1,则可用空间为较小的那个磁盘,较大的磁盘多出来的空间也可以分割成一个区来使用,不会造成浪费。
由于RAID1没有校验机制,如果用两个磁盘组成RAID1阵列,而两个硬盘上的数据因发生错误而变得不一致,RAID1就不知道应该相信哪一个硬盘。事实上,RAID1的磁盘数量越多,越有可能其中某两个磁盘的数据变得不一致,此时RAID1只会从第一个工作的硬盘中读取数据,但没有办法检测到底哪个硬盘的数据不对。
RAID2:位级分条汉明码校验
RAID2在RAID0的基础上进行了改进,采用了汉明码来实现数据差错的检测和纠正(ECC),这一方式被广泛使用于内存数据的差错检测和纠正中。使用汉明码将数据编码后,再按照RAID0的方式存放到磁盘中。RAID2存储的数据虽然比原始数据大一些(根据磁盘数量的不同,可能会多出12%-38%的校验数据),但是显著提升了数据的可靠性。
既然讲到了RAID2的ECC机制,我们就顺带回忆一下纠一位错的汉明码的编码方法。
编码后数据位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
编码数据位置 | p1 | p2 | d1 | p4 | d2 | d3 | d4 | p8 | d5 | d6 | d7 | d8 | d9 | d10 | d11 |
p1 | x | x | x | x | x | x | x | x | |||||||
p2 | x | x | x | x | x | x | x | x | |||||||
p4 | x | x | x | x | x | x | x | x | |||||||
p8 | x | x | x | x | x | x | x | x |
观察上表可发现一个比较直观的规律:第i个检验位是第2i-1位,从该位开始,检验2i-1位,跳过2i-1位,依次类推。例如上表中第3个检验位p4从第23-1=4位开始,检验4、5、6、7共4位,然后跳过8、9、10、11共4位,再检验12、13、14、15共4位。除此之外,n个校验位可以校验2n-n-1位的原始数据。例如上表中有4个校验位,原始数据的大小就是24-4-1=11位。
要检查某一位的错误,则需检查某一位所包含的所有奇偶校验位。这种错误的模式被叫做伴随式错误。如果所有奇偶校验位是正确的,就没有错误。除此以外的情况,错误的奇偶校验位的位置的和将识别错误的位。例如,如果位置为1、2、8的奇偶校验位指示了一个错误,那么位置为1+2+8=11的位出错了。如果只有一个奇偶校验位指示了错误,那么该奇偶校验位自身出错了。如果校验位组成的数字p1p2p4p8为0000,那么说明数据没有出错。
我们以数据100110102为例,求汉明编码后的码字。
- 列出表格,从左往右(或从右往左)填入数字,但2的次方的位置不填。
位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
数据 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
- 采用偶校验,第1位需要校验1、3、5、7、9、11位,所以第1位的值是0。
- 采用偶校验,第2位需要校验2、3、6、7、10、11位,所以第2位的值是1。
- 采用偶校验,第4位需要校验4、5、6、7、12位,所以第4位的值是1。
- 采用偶校验,第8位需要校验8、9、10、11、12位,所以第8位的值是0。
所以最终编码后的码字为0111001010102。
现在假设数据的第10位发生了错误,即数据变成了0111001011102,我们查看一下汉明码能否检查出错误。
- 检查第1位校验位,第1位需要校验1、3、5、7、9、11位,所以校验的值为0。
- 检查第2位校验位,第2位需要校验2、3、6、7、10、11位,所以校验的值为1。
- 检查第4位校验位,第4位需要校验4、5、6、7、12位,所以校验的值为0。
- 检查第8位校验位,第8位需要校验8、9、10、11、12位,所以校验的值为1。
最终校验的结果就是2+8=10,说明汉明编码成功帮我们找出是第10位数据发生了错误。
介绍完了汉明码的基本原理和方法,下面介绍另一种快速对数据进行汉明编码的方法。我们仍以数据100110102为例,求编码后的码字。
- 列出表格,从左往右(或从右往左)填入数字,但2的次方的位置不填。
位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
数据 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
- 把数据行有1的列的位置写为二进制。
位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
数据 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | ||||
二进制 | 0011 | 0111 | 1001 | 1011 |
将所有数据为1的位置的二进制数字求异或。
。 把1101从右至左依次填入表格中2的次方的位置(低位在左)。
位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
数据 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | ||||
二进制 | 0011 | 0101 | 1011 | |||||||||
校验 | 0 | 1 | 1 | 0 |
- 所以编码后的码字是0111001010102。
除了上述的可纠正一位错的汉明码之外,汉明通过增加一位校验位,提出了可纠正一位错或检测两位错的汉明码,具体的方法请读者自行查阅相关书籍。
采用RAID2的情况下,假如我们有4块数据盘,根据n位校验位的汉明码的位数公式,那么就需要有3块数据校验盘。
注意RAID2是位级分条的。
RAID3:位交错奇偶校验
RAID2采用了内存差错检测纠正(ECC)的方案,但实际上这是不必要的。由于磁盘控制器能够确定具体是哪一块硬盘发生了故障,所以我们并不需要复杂的汉明码来帮助差错检测和纠正。基于此,RAID3采用了一种简单的位交错奇偶校验码来实现硬盘数据的差错检测与纠正。相比于RAID2,RAID3只需要一块额外的校验盘,提高了硬盘的利用率。在实际的使用场景中,大多数情况下采用的也是RAID3而非RAID2方案。
和RAID2一样,RAID3采用了位级分条的方式,因此即使用户只读取一小段数据,也会导致所有的硬盘都处于工作状态,所以RAID3比较适于读取大量数据时使用。
示意图中的A、B、C、D表示长度为4bit的数据块(此处只是为了方便举例),它们的比特位按照位级分条的形式存放在磁盘1、2、3、4中,磁盘5中存放的是它们的校验位。
例如,A、B、C、D的数据和对应的校验位(默认采用偶校验)如下:
数据 | 0 | 1 | 2 | 3 | p |
---|---|---|---|---|---|
A | 1 | 0 | 1 | 1 | 1 |
B | 1 | 1 | 1 | 0 | 1 |
C | 0 | 0 | 1 | 0 | 1 |
D | 0 | 1 | 0 | 1 | 0 |
Ap是由A0、A1、A2、A3异或得到的。即
假如磁盘3发生了错误,那我们就可以根据校验磁盘恢复出磁盘3的数据。
RAID4:块交错奇偶校验
RAID4改进了RAID3的缺点,与RAID0一样使用了块级分条的策略,这样当用户读取一小段数据时,只会有一个硬盘和校验磁盘处于工作状态。RAID4也使用一个单独的校验磁盘来保存奇偶校验块。
如果有一个磁盘发生了故障,那么就可以通过奇偶校验块和其他磁盘上的块恢复该磁盘上对应块的数据。
我们仍假设一个块的数据大小为4bit,第一行(第一个条带)的示例数据如下表:
数据 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0号块 | 1 | 1 | 0 | 1 |
1号块 | 1 | 0 | 1 | 0 |
2号块 | 0 | 0 | 0 | 1 |
3号块 | 0 | 0 | 1 | 0 |
校验块 | 0 | 1 | 0 | 0 |
校验块的第0位数据是由0、1、2、3号块的第0位数据异或得到的。即
RAID5:块交错分布奇偶校验
RAID4已经有不错的效率了,但是还存在一个缺点,那就是每次校验数据时都需要使用同一块数据校验盘,这样大大降低了校验磁盘的使用寿命。RAID5通过将校验块旋转分布于所有的磁盘中,避免了大量读写校验盘的情况出现。
从图中可以看出,RAID5与RAID4大同小异,只不过是「旋转分布」了奇偶校验块的位置。
RAID6:P+Q冗余
RAID6在RAID5的基础之上额外增加了一块校验磁盘,进一步增加了安全性。原来的校验块记作P,新增的校验块记作Q,校验块P仍采用奇偶校验,而校验块Q通常采用别的差错检测纠正方法,比如里德-所罗门码,因此RAID6又称为P+Q冗余方案。
Storage Networking Industry Association (SNIA)对于RAID6的定义是:"在任意两块磁盘同时失效的情况下,仍然能够对RAID中的所有虚拟磁盘执行读写操作的RAID实现。“迄今已经有:(奇偶和里德-所罗门)双校验、正交双奇偶校验和对角奇偶校验等若干方法用于实现RAID 6。
由于两个独立的奇偶系统使用不同的算法,所以数据的可靠性非常高,任意两块磁盘同时失效时不会影响数据完整性。RAID6需要分配给奇偶校验信息更大的磁盘空间,同时也带来了额外的校验计算,相对于RAID5有更大的IO操作量和计算量,其“写性能”强烈取决于具体的实现方案,因此RAID 6通常不会通过软件方式来实现,而更可能通过硬件方式实现。
嵌套RAID
除了已经提到的原始的RAID方案,还有一些将它们组合起来使用的方式,
RAID10
RAID10(或RAID1+0)是RAID1和RAID0的组合,即先将磁盘镜像再进行条带化。
RAID01
RAID10(或RAID1+0)则是RAID0和RAID1的组合,即先将磁盘条带化再进行镜像。RAID0的条带化可以提供并行访问的能力,提升性能,RAID1的镜像则提升了整个系统的容错能力。
总结
RAID2、3、4较少实际应用,因为RAID0、RAID1、RAID5、RAID6和混合RAID已经涵盖所需的功能,因此RAID2、3、4大多只在研究领域有实现,而实际应用上则以RAID0、RAID1、RAID5、RAID6和混合RAID为主。