今天码哥给大家带来一种数据备份与修复的技术——里德所罗门编码。
里德所罗门编码可是应用场景很多,例如我们耳熟能详的RAID(磁盘阵列),又例如在UDP传输中降低丢包导致的数据缺失的情况等等。
这里,先要介绍一种纠错方法——极大距离可分法(MDS)。这是一种很常见的纠错方法,它将原始数据分成等长的N份,并根据这N份数据生成M个冗余的校验数据。此时,M+N块数据中任意M块数据损失,也可以通过剩余N块数据经过计算来恢复原始数据。
里德所罗门纠错算法就是经典的MDS算法。
这里我们那先不过多解释,大家先对矩阵型形式混个脸熟,至于伽罗华域我们后面会说到。
在开始前,我们不得不引入一个数学问题——插值问题。
在一些工程实践中,某些变量间是存在函数关系的,但通常不能用公式表示,只能用实验观测得到y=f(x),即一系列xi在函数上的值。有些公式非常复杂,计算其完整公式并不划算,因此我们希望用另一个函数p(x)来尝试逼近f(x)。
此时,假设在二维空间中有n个点,(x1, y1), (x2, y2), …, (xn, yn),希望得到一个多项式的解:
这个多项式可以满足我们的当前条件:
实际上,可以推演如下:
可以看到矩阵A即为范德蒙矩阵,而如果每个点的x值互不相同,那么范德蒙矩阵的行列式值必不为零(略过证明),那么矩阵A就存在逆矩阵。
由此,我们那可以看到,通过对插值问题的讨论,我们发现了一种数据恢复方式,即:
矩阵A * 矩阵B = 矩阵Y
矩阵A的你矩阵 * 矩阵Y = 矩阵B
下面,我们来说一下在里德所罗门编码中如何进行的编解码的。
例如,我有两段数据:
data = [
[1,2,3,4],
[5,6,7,8]
]
下面是构建系数矩阵A,A的构建方式是,上方为一单位矩阵,下方是范德蒙矩阵,且:
那么构建出的系数矩阵A为:
A = [
[1, 0],
[0, 1],
[1, 1]
]
编码即为矩阵乘法,得到的结果为:
result = data * A = [
[1,2,3,4],
[5,6,7,8],
[6,8,10,12]
]
可以看到,前两行与原始数据一样,最后一行则是冗余数据。
下面,我们来模拟解码过程,假设我们丢失了第二个数据[5,6,7,8],那么恢复过程如下:
首先,构建系数矩阵A':
A' = [
[1, 0],
[1, 1]
]
可以看到,我们跳过了[0, 1],是因为该行对应的数据丢失了,因此构建时也要相应去掉。
然后我们要对A'求逆,得到A'':
A'' = [
[1, 0],
[-1, 1]
]
最后,利用矩阵乘法恢复原始数据:
data = A'' * B = [
[1,2,3,4],
[5,6,7,8]
]
到此,似乎已经完成了数据丢失后的恢复,但细心的读者可能发现了,在计算逆矩阵的时候可能会存在小数,会造成精度损失,因此,恢复后的数据会和原始数据不一致。
这就是我们接下来要介绍的,数域的作用。
为了避免矩阵运算中出现小数导致的精度损失,我们要将整个矩阵运算从实数域迁移到伽罗华域中。
伽罗华域是一种有限数域,其值范围为[0, 2^8-1],即0~255。
那么如何进行迁移呢?答案很简单,我们将矩阵中用到的加减乘除四则运算进行一些变换。
在伽罗华域中:
由于本篇为纯理论类文章,涉及较多数学概念,如有纰漏还望告知,感谢您的观看!