分布式系统的容错性(二)——检错和纠错

版权声明:欢迎转载博主的原创文章,但请注明出处。 https://blog.csdn.net/DLite/article/details/3026842

 

本系列内容是我学习分布式系统容错性的一些笔记,欢迎就相关内容进行讨论。

我的联系方式:DLite@163.com 

2007-11-26

==============================================       

人们已经研究出两种基本的策略用于错误处理过程。一种方法是在信息块中包含足够的冗余信息,以便推断出这些数据中肯定有哪些内容,即使用纠错码(error-correcting code)的策略。另一种也是包含一些冗余信息,但是这些信息只能推断出发生了错误,却推断不出发生了哪些错误,即使用检错码(error-detecting code)的策略。使用纠错码的技术通常也被称为前向纠错(forward error correcting)

        每一项技术都有不同的适用环境。在高度可靠的信道上,比如光纤,比较合理的做法是使用检错码,当偶尔发生错误时,只需重传整个数据块即可。然而,在错误发生频繁的信道上,比如无线链路,最好的做法是在每个数据块中加入足够的冗余信息,以便接收方计算出原始的数据是什么。

        1、利用海明码纠错

        假设一个n位长数据块,包含m个数据位和r个冗余位(校验位),即n=m+r。包含数据和校验位的n-位单元通常也称为n位码字(codeword)。给定两个码字,比如10110111和11110110,我们可以确定它们有多少个位对应不同。即两个码字异或(XOR)运算结果中1的个数,在这个例子中有2位不同:

        10110111

        11110110

        -----------

        01000001

        两个码字中不相同的位的个数称为海明距离(Hamming distance)。它的意义在于,如果两个码字的海明距离为d,则需要d个1位错误才能将一个码字转变称另一个码字。

        注:在科学术语中,海明本人更希望Hamming的第一个字母“H”用小写“h”。

        在大多数应用中,所有的2^m种可能的数据块都是合法的,但根据校验位的计算方法,并非所有2^n种可能的码字都被用到了。给定了计算校验位的算法以后,我们有可能构造出完整的合法码字表,并且从这个列表中找到海明距离最小的两个码字。此距离是这整个编码方案的海明距离。

        为了检测d个错误,需要一个距离为d+1的编码方案,因为在这样的编码方案中,d个1位错误不可能将一个有效码字改变成另一个有效码字。为了纠正d个错误,需要一个距离为2d+1的编码方案,因为这样的编码方案中,即使由于错误发生了d位变化,还是原来的码字离它最近。

        在2^n个串模式中,有2^m个正确的模式。对于每个模式,如果允许一位错误,则共有n+1种可能的编码。因此,为纠正1位错误,所需要的校验位数目的下界由下式确定:

        (n+1)2^m≤2^n

        由于n=m+r,上式也可表示为:

        m+n+1≤2^r

        实际上,根据海明(1950年)提出的方法,这个理论下界是可以达到的。码字中的每一位连续编号,从最左边位1开始,它的右边是位2,等等。编号为2的幂次方的位(1,2,4,8,16,…)为校验位。一个位可能包含在几次奇偶值计算中。我们将k重写成2的幂次方的和,例如11=1+2+8。只有出现在k的展开式中的这些控制位才能校验k上的数据位。

         hamming

          图1 利用海明码纠正突发性错误

        海明码只能纠正单个错误。将k个连续的码字排成一个矩阵,每行一个码字。通常情况下,每次从左向右传输一个码字。为了纠正突发性的错误,传输数据时每次发送一列,从左边的列开始。如果一个突发性错误的长度为k位,则在k个码字中,每个码字之多只有1位受到影响。而利用海明码每次可以纠正一个错误,所以整个数据块也可以恢复出来。这种方法利用kr个校验位,使km个数据为能够抵抗长度等于或小于k的单个突发性错误。

        2、检错码

        在错误率非常低的系统中,比如光纤通信系统,利用错误检测和重传机制恢复数据,往往比使用纠错码更有效。

        首先被想到的方法是使用奇偶校验位。但是,如果在一个数据块中只增加了一个奇偶位,则在发生一段很长的突发性错误时,该错误能被检测出来的概率只有0.5,这是难以接收的。采用和前面类似的方法,可以把每一块数据当作一个n矩阵(n位宽,k位高),为每一列单独计算一个奇偶位,并将它附在矩阵的下边作为最后一行,然后按每次一行传输该矩阵数据,则检测出错误的概率会显著增加。 用这种方法可以检测出长度小于等于n的单个突发性错误,因为每列只有一位被改变了。在n列中,任何一列有正确的奇偶位的概率是0.5,所以,一个坏块被当作正确数据块接受的概率为1/2^n,

        尽管上述方案有时候已经足够了,但是在实践中,广泛使用的是另外一种方法:多项式编码(polynomial code),也称为CRC(Cyclic Redundancy Check,循环冗余校验码)。多项式编码的基本思想是:将位串看成是系数为0或1的多项式。一个k位的数据块看作是一个k-1次多项式系数表,该多项式共有k项,从x^(k-1)到x^0。多项式的算术运算规则采用代数域理论的规则,以2为模来完成。

        polydiv

         图2 多项式除法的例子

        使用多项式编码时,通信双方必须预先商定一个生成多项式(generator polynomial)G(X)。生成多项式的最高位和最低位必须是1。假设一个帧有m位,它对应于多项式M(x),为了计算它的校验和(checksum),该帧必须比生成多项式长。基本的思想是在帧的尾部追加一个校验和,使得追加之后的帧所对应的多项式能被G(x)除尽。接收方受到了带校验和的帧以后,它试着用G(x)去除它。假如有余数的话,则表明传输过程中有错误。

       计算校验和的算法如下:

       1)假设G(X)的阶为r。在帧的低位端加上r个0位,所以该帧现在包含m+r位,对应多项式为x'M(x)。

       2)利用模2除法,对应于G(x)的位串取出对应于x'M(x)的位串。

       3)利用模2减法,从对应于x'M(x)的位串中减去余数。结果就是将被传输的带校验和的帧。它的多项式不妨设为T(x)。

       假设在传输的过程中发生了错误,接收方接收到的不是T(x),而是T(x)+E(x)。收到数据后,接收方用G(x)来除它,即计算[T(x)+E(x)]/G(x)。由于T(x)/G(x)是0,所以计算的结果是E(x)/G(x)。如果错误多项式E(x)恰好包含G(x)作为它的一个因子,则这样的错误将无法检测到;否则,其他的错误都能够被检测到。

       多项式编码的几个特性:

       1)没有一个奇数项多项式包含x+1作为因子。因此,以x+1作为G(x)的因子,可以捕获到所有包含奇数个位数变反的错误。

       2)带r个校验位的多项式编码可以检测到所有长度小于等于r的突发性错误。

       3)当一个长度大于r+1位的突发性错误发生的时候,或几个短一点突发性错误发生的时候,一个坏帧被当作有效帧而通过检测的概率为(1/2)^r,这里假设所有的位模式都是等概率的。

       有些多项式已经成为国际标准了,其中在IEEE802中使用的多项式为:

       polycode

       此多项式能检测到所有长度小于等于32的突发性错误,以及只影响奇数个位的突发性错误。

       Peterson和Brown(1961年)已经证明了,可以用硬件构造一个简单的移位寄存器电路来计算和验证校验和。在实践中,几乎总是采用这种硬件来实现多项式校验。

       需要注意的是,以上校验和算法基于被校验数据的随机性假设。实际在某些情况下,未检测出来的错误比原先想象的多得多。

       参考文献:

       Andrew S. Tanenbaum 著,潘爱明译,《计算机网络(第4版)》,2004,清华大学出版社。

展开阅读全文

没有更多推荐了,返回首页