纠删码

568 阅读18分钟

一、背景与挑战

数据的爆炸式增长使得存储系统的规模不断增加,存储设备的可靠性却一直没有得到显著提高(SSD 从SLC 到MLC 和TLC 可靠性不断下降,磁盘随着单位面积写入数据更多导致可靠性无法提升),从而给数据的持久化存储带来巨大挑战。另外随着存储系统规模的增大,存储系统中的冷数据的增加将远超过热数据的增加,如何安全保存冷数据,在需要的时候能够获取冷数据也成为存储系统中的重要挑战。

二、冗余机制

本策略和编码策略是保证数据冗余度的两个重要方法。当原始数据发生部分丢失时,副本策略和编码策略都可以保证数据仍旧可以正确获取。副本策略将原始数据拷贝一份或多份进行存储,编码策略则将原始数据分块并编码生成冗余数据块,保证丢失一定量内的数据块,原始数据仍旧可以获取。

图1. 副本策略

图2. 编码策略

两种策略性能比较如下:

存储效率计算开销修复效率
副本策略
编码策略

ErasureCode(纠删码)以更低成本的方式提供近似三副本的可靠性,吸引众多分布式存储/云存储的厂商和用户。

故障容忍+数据冗余 选择更灵活

虽然编码策略比副本策略存在计算开销和修复效率低的缺点,但能够极大的减少存储开销的优势还是为编码策略赢得了巨大的空间。实际中,存在着副本策略和编码策略的存储系统,比如在分布存储系统(HDFS, GFS, TFS)中热数据往往通过副本策略保存,冷数据则通过编码后保存,节省存储空间。在ECC内存和SSD的page 中也使用了ECC 编码策略保证数据冗余。

下面通过一个方程组的例子啰嗦下这两种策略,如果将原始数据比作如下一个方程组S(x 和 y对应着原始数据的两部分):

x = 1

y = 2

副本策略复制相同一个方程组S’ ,当任何一个等式失效时,仍然得到相同的方程组:

x = 1 x = 1

y = 2 y = 2

编码策略则是通过线性组合这两个方程组得到一个新的方程

x = 1

y = 2

2(x) + (y) = 4

这样就保证了三个方程中任意两个都可以线性组合得到x 和y 的值。

三、什么是纠删码

1.误码控制的不同功能

    • 检错
      • 检错码仅具备识别错码功能而无纠正错码功能
    • 纠错
      • 纠错码不仅具备识别错码功能,同时还具备纠正错码功能
    • 纠删
      • 纠删码则不仅具备识别错码和纠正错码的功能,而且当错码超过纠正范围时,还可把无法纠错的信息删除。

2.存储单元连接方式

    • 基于高速总线方式的磁盘阵列
      • 阵列码是一种特殊化的纠删码,其采用高效率的异或运算(XOR),如RAID5、RAID6等
    • 基于LAN方式的集群存储
      • 集群存储系统中,如HDFS的HDFS-RAID、PanFS支持RAID-5容错编码、Google的GFSⅡ、微软的WAS等
      • 开源的集群存储系统中,如GlusterFS的EC卷、ceph纠删码等
    • 基于WAN/Internet方式的广域网络存储系统
      • 广域网下,如RACS、DepSky等

3.纠删码

    • Reed-Solomon类
      • RS类码是唯一可以满足任意磁盘数目N和校验数据M中丢失M块后能恢复的Maximum Distance Separable(简称MDS)编码
    • 级联低密度纠删码LDPC(LowDensity Parity Check Code)纠删码
    • • 数字喷泉码

四、纠删码中的MDS性质

MDS 性质是纠删码的一个重要性质,它保证n=k+m 个磁盘中任意k 个磁盘都可恢复出k 个数据盘,或可表示为该编码容忍任意m=n-k 个磁盘发生故障,而数据不发生丢失。传统的RS 码具有MDS 性质。

总数据块 = 原始数据块 + 校验块

n = k + m

允许故障:任意m个块,包括原始数据块 和 校验块

从k个原始数据块中计算出m个校验块。

将这k+m个数据块分别存放在k+m个硬盘上,就能容忍任意m个硬盘故障。

当出现硬盘故障时,只要任意选取k个幸存数据块就能计算得到所有的原始数据块。

同理,如果将k+m个数据块分散在不同的存储节点上,就能容忍m个节点故障。

n = k + m

  • k值影响数据恢复代价。k值越小,数据分散度越小,故障影响面越大,重建代价也就越大;k值越大,多路数据拷贝增加的网络和磁盘负载越大,重建代价也越大。
  • m值影响可靠性与存储成本。取值大,故障容忍度高;m 取值小,数据冗余低。在两者之间权衡。
  • k 取值 有时候也和数据块对齐,k/m 按照磁盘故障率来选择。

五、基本原理

Reed-Solomon(RS)码是存储系统较为常用的一种纠删码,它有两个参数n和m,记为RS(n,m)。n代表原始数据块个数。m代表校验块个数。接下来介绍RS码的原理。

1.编码矩阵

从信息论和编码的角度来说,纠删码属于分组线性编码。其编码过程可以通过一个编码矩阵GM 和分块数据的乘法(点积)来表示,也就是说编码矩阵GM 定义了数据是如何编码为冗余数据的。以图4、图5 为例,C0 ~ C5 是冗余数据,所有的冗余数据可以表示为GM × D{D0、D1、D2、D3} 的乘法,每一个冗余数据块Ci 是矩阵的对应的一行和数据块的乘积(黄色标示)。编码矩阵中GM 每一个元素则是对应原始数据块的乘法系数。编码矩阵的列数对应着原始数据分块个数(n),行数对应着编码后所有数据块个数。

图4. 编码过程可以看做编码矩阵GM 和数据块的乘积

图5. 编码过程的数学表示

如果一个编码是系统码,则编码矩阵的前n 行构成一个n×n 大小的单位矩阵,剩余后k-n = m 行构成m×n 大小的校验矩阵(parity matrix)。单位矩阵和原始数据的乘法得到的还是原始数据,校验矩阵和原始数据的乘法得到校验数据

2.RS码编码原理

以n=5,m=3为例。即5个原始数据块,乘上一个(n+m)n的矩阵,然后得出一个(n+m) 1的矩阵。根据矩阵特点可以得知结果矩阵中前面5个值与原来的5个数据块的值相等,而最后3个则是计算出来的校验块。

以上过程为编码过程。D是原始数据块,得到的C为校验块。

假设丢失了m块数据。如下:

那我们如何从剩余的n个数据块(注意,这里剩余的n块可能包含几个原始数据块+几个校验块)恢复出来原始的n个数据块呢,就需要通过下面的decoding(解码)过程来实现。

第一步:从编码矩阵中删去丢失数据块和丢失编码块对应行。 将删掉m个块的(n+m)1个矩阵变形为n1矩阵,同时B矩阵也需要删掉对应的m个行得出一个B'的变形矩阵,这个B'就是n*n矩阵。如下:假设D1、D4、C2丢失,我们得到如下B’矩阵及等式。

第二步:求出B’的逆矩阵。

第三步:等式两边分别乘上B’的逆矩阵。

B’和它的逆矩阵相乘得到单位矩阵I,如下:

左边只剩下原始数据矩阵D:

至此完成解码过程。

六、RS的特点

  • 低冗余度,高磁盘利用率。
  • 数据恢复代价高。 丢失数据块或者编码块时, RS需要读取n个数据块和校验块才能恢复数据, 数据恢复效率也在一定程度上制约了RS的可靠性。
  • 数据更新代价高。 数据更新相当于重新编码, 代价很高, 因此常常针对只读数据,或者冷数据。

工程实践中,一般对于热数据还是会使用多副本策略来冗余,冷数据使用纠删码。

七、RS数学原理

1.RS矩阵种类

Vandermonder矩阵

在上面中,为了恢复原数据,需要计算编码矩阵(这里指的是C1)的逆矩阵,这也是为什么上面编码矩阵是由一个单位矩阵和一个Vandermonder矩阵组成的,因为Vandermonder矩阵任意两行之间都线性无关,可以求解出逆矩阵。

2.伽罗华域

RS纠删码是按照word为单位对数据进行编解码,这也就要求对一个字进行编码后,产生的结果仍然是一个字,因此RS纠删码基于伽罗华域GF(2^n)及其四则运算来进行编解码。

数学概念

单位元

Identity Element,也叫幺元(么元),通常使用e来表示单位元。单位元和其他元素结合时,并不会改变那些元素。 对于二元运算 ,若ae=a,e称为右单位元;若ea=a,e称为左单位元,若ae=e*a=a,则e称为单位元。

逆元

对于二元运算 ,若ab=e,则a称为b的左逆元素,b称为a的右逆元素。若ab=ba=e,则称a为b的逆元,b为a的逆元。

本原多项式

域中不可约多项式是不能够进行因子分解的多项式, 本原多项式 (primitive polynomial)是一种特殊的不可约多项式。当一个域上的本原多项式确定了,这个域上的运算也就确定了。本原多项式一般通过查表可得,同一个域往往有多个本原多项式。

通过将域中的元素化为多项式形式,可以将域上的乘法运算转化为普通的多项式乘法再模本原多项式。

多项式运算

1、多项式加减法

将两个多项式中相同阶数的项系数相加或相减。 例如 (x2 + x ) + (x + 1) = x2 + 2x +1

2、多项式乘法

将其中一个多项式的各项分别与另一个多项式的各项相乘,然后把相同指数的项的系数相加。 例如 (x2 + x) * (x + 1) = x2 * (x + 1) + x * (x + 1) = x3 + x2 + x2 + x

3、多项式除法

使用长除法。例如计算x3-12x2-42,除以x-3。使用长除法计算,商x2-9x-27,余数-123。

4、GF(2^w)上的多项式运算

对于GF(2^w)上的多项式计算,多项式系数只能取 0或1。(如果是GF(3w),那么系数可以取 0、 1、 2) GF(2^w)的多项式加法中,合并阶数相同的同类项时,由于0+0=0,1+1=0,0+1=1+0=1,因此系数不是进行加法操作,而是进行异或操作。

GF(2^w)的多项式减法等于加法,例如x ^4 – x^4就等于x^4 + x^4。

群(Group)

我们在一个集合上定义一个二元运算,这就是数学中的群。比如,二元运算-->“加法”并用符号“+”表示,(可以任意符号任意名字,也可以这么理解:一个群,由自身的集合和二元运算符‘+’组成),为了使集合 [公式] 成为一个群,必须满足以下四个条件:

封闭性(closure):如果a和b被包含于 [公式] ,那么a+b 也一定是 [公式]的元素。

结合律(associativity)。

存在一个单位元(identity element)0,使得 a+0 = 0+a = a;[单位元:与任意元素运算不改变其值的元素]

每个数都存在一个相反数(inverse)。

如果我们再加上第五个条件:

  1. 交换律(commutativity):a+b = b+a.

这个群就叫做阿贝尔群(abelian group)。

从我们通常的加法概念来看,整数集 [公式] 是一个群(而且是一个阿贝尔群)。自然数集 [公式] 不是一个群,因为它不满足第4条。

群是非常好的,因为如果我们可以证明这四条属性,那么我们可以直接拿来用其他的属性了。比如,有且只有一个单位元,对应的相反数也是独一无二的,那么不论直接还是间接,关于群的所有属性和结论我们都可以随意使

有限域GF(p)

首先,有限域是一个带有有限元素的集合。比如,有一个有限域是整数模p的集合(integers mod p,p是素数),可表示为 ,我们一般用后者。

在这个有限域中,我们有两个二元操作:加(+)和乘( * )。这两种操作都是封闭的,满足结合律和交换律,[这块的封闭应当这样理解:在有限域中,两个数的加和乘的结果仍然在这个有限域中。--译者注] 且含有一个独一无二的单位元,对于所有的有限域里的元素,都有一个独一无二的相反数。最后,乘法还满足分配律:

整数模p的集合包含所有从0到 的整数。加法和乘法都按模数运算规则去计算。这里有一些 的例子:

  • 加:
  • 减:
  • 乘:
  • 加法逆元: 的确:
  • 乘法逆元: 的确:

基于域中元素的多项式

在基础数学中,多项式可以表示为如下形式,其中 为多项式的系数,系数可以是任意整数、甚至复数,多项式可以进行加法、减法、乘法、除法等操作。

如果我们将多项式的系数限定于有限域GF(q)中的元素,并且基于有限域中的运算规则重新定义多项式的加减乘除操作,那么这样的多项式集合称为 基于有限域的多项式。假设有两个基于有限域的多项式a(X)和b(X):

定义多项式的加法

其中 + 是指在GF(q)中的 modulo-q加法。

定义多项式的乘法

其中:

多项式的减法定义为:

其中, 称为 元素的加法逆,与 满足 ,上述 + 是在GF(q)中的 modulo-q加法。

定义多项式的除法

其中q(X)和r(X)分别称为商和余数,显然deg(r(X)) < deg(b(X))(deg称为多项式的阶数,即多项式的最高阶数),该操作也称为欧几里德除法算法,下面通过基于GF(5)中的实例来说明基于有限域的多项式除法。

定义1: 如果m阶多项式 不能被基于有限域GF(q)中的任何多项式整除,称 为不可约多项式。

定理2: 有限域GF(q)­任意的m阶不可约多项式 ,都可以整除 ,即 为除数, 为被除数,相除后余数为0。

定义2:如果不可约多项式 能够整除 的最小整值取值为 ,那么称 为本原多项式

有限域GF(2^w)(伽罗华域)

GF(p)中p必须是一个素数,才能保证集合中的所有元素都有加法和乘法逆元(0除外)。但实际应用中,很多场合需要 0到255这256个数字能组成一个域。但256不是素数,小于256的最大素数为251,如果直接把大于等于251的数截断为250,则会丢失一部分数据。

因此引入了GF(p^w),其中p为素数,通常取p=2。计算机领域中经常使用的是GF(2^8),8刚好是一个字节的比特数。为了保证单位元性质,GF(2^w)上的加法运算和乘法运算,不再使用一般的加法和乘法,而是使用多项式运算。

通过将域中的元素化为多项式形式,可以将域上的乘法运算转化为普通的多项式乘法再模本原多项式。

通过本原多项式生成元素

设P(x)是GF(2^w)上的某一个本原多项式,GF(2^w)的元素产生步骤是:
1、给定一个初始集合,包含0,1和元素x,即 {0,1,x};
2、将这个集合中的最后一个元素,即x,乘以x,如果结果的度大于等于w,则将结果mod P(x)后加入集合;
3、直到集合有2^w个元素,此时最后一个元素乘以x再mod P(x)的值等于1。

例如,GF(2^4)含有16个元素,本原多项式为P(x)=x^4+x+1,除了 0、1外,另外14个符号均由本原多项式生成。 注意到x^14=x3+1,此时计算x^15=x^14x=(x^3+1) x=x^4+x=1,生成结束。

4、确定本源多项式后就要把x定义为P(x) = 0的根,即x^4+x+1=0 x^4=x+1 多项式系数不能超过w

生成元素多项式表示二进制表示数值表示#### 推导过程
0000000
x^0x^000011
x^1x^100102
x^2x^201004
x^3x^310008
x^4x+100113x^3*x = x^4 mod P(x) = x+1
x^5x^2+x01106x^4*x = (x+1)*x = x^2+x
x^6x^3+x^2110012
x^7x^3+x+1101111x^6*x = (x^3+x^2)*x = x^4 +x^3 mod P(x) = x^3+x+1
x^8x^2+101015
x^9x^3+x101010
x^10x^2+x+101117x^9*x=(x^3+x)*x = x^4+x^2 mod P(x) = x^2+x+1
x^11x^3+x^2+x111014
x^12x^3+x^2+x+1111115x^11*x=(x^3+x^2+x)*x = x^4+x^3+x^2 mod P(x) = x^3+x^2+x+1
x^13x^3+x^2+1110113x^12*x=(x^3+x^2+1 )*x = x^4+x^3+x mod P(x)= x^3+1
x^14x^3+110019x^13*x=(x^3+x^2+1)*x = x^4+x^3+x mod P(x) = x^3+1
x^15100011x^14*x = (x^3+1)*x = x^4+x mod P(x) = 1

通过查表简化伽罗华域计算

生成元。

生成元是域上的一类特殊元素,生成元的幂可以遍历域上的所有元素。假设g是域GF(2^w)上生成元,那么集合 {g0 ,g1 , ……,g(2^w-1) } 包含了域GF(2^w)上所有非零元素。在域GF(2^w)中2总是生成元。

将生成元应用到多项式中, GF(2^w)中的所有多项式都是可以通过多项式生成元g通过幂求得。即域中的任意元素a,都可以表示为a = g^k。

GF(2^w)是一个有限域,就是元素个数是有限的,但指数k是可以无穷的。所以必然存在循环。这个循环的周期是2^w-1(g不能生成多项式 0)。所以当k大于等于2^w-1时,gk =g^k%(2^w-1)。

对于gk = a,有正过程和逆过程。知道指数k求a是正过程,知道值a求指数k是逆过程。

对于乘法,假设a=g^n,b=g^m。那么ab = g^n g^m = g^n+m。查表的方法就是根据a和b,分别查表得到n和m,然后查表g^n+m即可。

因此需要构造正表和反表,在GF(2^w)域上分别记为gflog和gfilog。gflog是将二进制形式映射为多项式形式,gfilog是将多项式形式映射为二进制形式。

注意:多项式0 ,是无法用生成元生成的。g0等于多项式1,而不是 0。

根据上文的GF(2^4)的元素表示,生成gflog表和gfilog表如下:

查表进行乘法和除法运算的例子

在GF(2^4)域上的乘法和除法,已知2^w-1 = 2^4 -1 = 15:

乘法:

7 * 9 = gfilog[gflog[7] + gflog[9]] = gfilog[10 + 14] = gfilog[24 mod 15] = gfilog[9] = 10

除法:

13 / 11 = gfilog[gflog[13] - gflog[11]] = gfilog[13 - 7] = gfilog[6] = 12

例子

假设原始数据 D, Vandermonde 矩阵 F, 冗余数据 C,则:

上面计算矩阵F时,根据GF(2^4)的计算规则,3^2^ = 3*3 = gfilog(gflog(3)+gflog(3)) = 5

将矩阵F与3*3的单位矩阵E集合,可得:

根据上面的定义,任意丢失3份数据,都可以恢复原来的数据,这里假设丢失了D2,D3和C3,则恢复过程:

可以看到,成功恢复原来的数据。

计算过程