alan.wzj@gmail.com

RAID6 是目前存储领域常用的磁盘阵列配置,其最多可以容忍两块磁盘同时损坏,而不会造成数据的丢失。但是,在实际应用中,由于磁盘生命周期的同步性;用户 I/O 性能和数据重构之间的矛盾,导致传统 RAID6 越来越不能满足存储应用需求。但是, RAID6 的思想是经典,基于 RAID6 算法,我们可以扩展对磁盘故障率容忍度更高的算法,配合存储虚拟化技术实现可靠性更高的存储系统。这里对 RAID6 算法进行详细剖析和讨论。
RAID6的数学方程
 
RAID6 通过两块数据冗余盘实现条带数据的保护,最坏情况下可以允许两块磁盘的同时损坏。为了达到这个目的, RAID6 有两种校验码, P 码和 Q 码。从数学的角度讲, P Q 校验码的计算方法如下:
将上述方程转换成矩阵形式,我们就可以很容易的看出 RAID6 数据编码的原理:
 
从这个矩阵方程看出, (n+2, n) 校验矩阵线性无关, P Q 是D0 ~Dn-1 的线性组合。通过校验矩阵,可以将原始数据D0 ~Dn-1 映射成D0 ~Dn-1 ,P,Q,从而达到数据冗余的目的。
通过上述方程, RAID6 的基本数学原理已经比较清楚了,当系统接收到数据之后,通过校验矩阵,可以得到最终的编码数据。由于校验矩阵格式是标准的,原始数据无需编码,所以,只需要计算 P Q 校验数据。
RAID6计算域
 
显而易见, RAID6 的引入增加了 I/O 过程中的计算量,必将影响到 I/O 的整体性能,因此, RAID6 实现过程中一个很重要的问题就是如何高效计算 PQ 校验码?对于 P 编码,计算量比较小,直接可以进行 XOR 运算,但是, Q 编码涉及到大量的乘加运算,没有特殊的硬件支撑,很难提高 IO performance
针对这个问题,这里引入很重要的迦罗华域( GF ),迦罗华域是一个有限循环域,域中的元素通过本原多项式产生。 RAID6 采用 GF(2^8 ) ,本原多项式为: P(x) = x8 + x4 +x3 + x2 + 1 。通过这个本原多项式,可以得到有限域中的所有元素:

  迦罗华域中的加减法运算等价于 XOR 操作,因此,在该域进行数据编解码操作可以大大降低复杂度。
对于 RAID6 而言,面临的另一类运算是乘法运算,如何降低乘法运算带来的计算复杂度呢?这里,我们可以通过对数运算降低计算复杂度。
 
通过对数运算,我们把复杂的乘法运算转换成了加法运算( XOR ),因此,现在问题的关键是如何完成对数和反对数运算。考虑到迦罗华域的有限性,我们可以把域中元素对应的对数 / 反对数做成表格,然后通过查表的方式,实现 Q 编码的快速运算。
仔细观察迦罗华域元素生成表格,我们可以发现,在迦罗华域中进行对数 / 反对数的运算很简单,因为所有域元素都是本原元 a n 次幂,所以,可以很容易的得到对数 / 反对数表格。
由此,我们可以得出,迦罗华域是 RAID6 的运算域, Q 码的运算可以通过对数 / 反对数表格转换成普通的加法运算,在迦罗华域加法运算等价于 XOR 。因此, RAID6 所有运算都可以转换成 XOR 异或运算。
RAID6计算方法讨论
软件计算方法
 
考虑到降低计算运算量,充分利用软件的灵活性,我们可以在内存中直接生成迦罗华域的正反对数表,软件可以通过简单的查表和 XOR 操作完成 Q 码计算。
对数 / 反对数表的生成的示例程序如下所示:
  alog[0] = 1;
for (i=1; i<256; i++) {
                alog_data = alog[i-1] * 2;
                if (alog_data >= 256) {
                                alog_data ^= 285; // 本原多项式
}
alog[i] = alog;
log[alog[i]] = i;
}
由此,我们可以得到如下两张迦罗华域的对数 / 反对数表格:
 

 

有了正反对数表格之后,计算 Q 码的设计思想可以表述如下:
1, 在迦罗华域对每个输入数据和其对应的系数相乘
a.       通过正对数表 (log) 分别找到系数和输入数据对应的值 d1 d2
b.      d1 d2 进行异或运算,得到 c1
c.       通过反对数表格 (alog) ,找到 c1 对应的值 d1
2, 将第一步得到的所有结果异或起来,得到最终结果
由此可见,在迦罗华域 Q 码的计算量不是很大,主要是查表和异或操作。
在实现过程中,我们可以将迦罗华域的乘法运算封装成如下函数:
unsigned int xor_multiple(unsigned int a, unsigned b)
{
                If (a == 0 || b == 0) {
                                Return 0;
}
d1 = log[a];
d2 = log[b];
c1 = d1 ^ d2;
d1 = alog[c1];
return d1;
}
另外, Intel 的处理器提供了 SSE 指令集,我们也可以采用 SSE 指令实现对 RAID6 算法的加速。
硬件计算方法
 
如果采用硬件的方式实现 RAID6 算法,如何做才能达到最高效呢?当然,我们也可以采用软件的思想,采用正反对数表和状态机实现 Q 码运算。对于这种实现方案,由于正反对数表太大,不可能全部采用寄存器的方式进行存储,只能采用 SRAM 存储这些表格,那么,流水线需要考虑的延迟单元就是访存延迟。所以,个人觉得这种实现方案不一定是最佳的。
 
软件最大的好处在于灵活性,硬件最大的好处在于快速处理简单的重复事情。因此,我们有必要再看一下 Q 码的数学方程,从中找一些更加符合硬件运算的规律。
通过数学化简,我们可以得到如下的 Q 码方程:

 

从中,我们可以发现一个规律,整个运算过程只涉及到 A*g 的乘法运算和加法运算。因此,只需要设计很简单的乘法器便可以完成 Q 码运算。但是,这种方法已存在一个问题:无法实现输入数据的并行处理,输入数据之间存在流水相关性。这里仅仅提出这种思想,以供讨论。