数据丢失常见的恢复方法
假设有一个客户端和一个服务器,客户端和服务器通过网络连接,但是这个网络很不稳定,可能会出现丢包,那么怎么样才能在服务器端恢复那些丢失的数据呢。通常有两种做法:
- 通知客户端重传丢失的数据。
- 客户端根据原始数据生成一组冗余数据,然后把原始数据和冗余数据一起发送给服务器,只要丢失的数据量不超过阈值,服务器就可以根据未丢失的原始数据和冗余数据来恢复那些丢失的原始数据。
本文介绍的是第二种方法,通过加冗余的方式来保护原始数据。
异或的特性
异或的一个重要特性:恢复数据。
假设有两个数num1和num2,他们异或的结果是num3,那么num3和num1异或之后等于num2,num3和num2异或之后等于num1。也就是说,num1丢失了,可以通过num2和num3进行恢复;num2丢失了,可以通过num1和num3进行恢复。
num1 = 10;
num2 = 12;
num3 = num1 ^ num2; // num3是num1和num2异或的结果
assert(num3 ^ num1 == num2);
assert(num3 ^ num2 == num1);
使用异或来保护数据
假设,客户端需要把a、b、c、d四个整数发送给服务器,为了保护数据,使用异或操作生成了四个冗余数据:fec1、fec2、fec3、fec4,客户端把a、d、c、d、fec1、fec2、fec3、fec4一起发送给服务器,由于网络不稳定,发生了突发丢包,导致c、d、fec1、fec2丢失,那么服务器可以通过a、b、fec3、fec4这四个包恢复c和d
// 原始数据
int a = 1, b = 2, c= 3, d= 4;
// 通过异或操作生成的冗余数据
int fec1 = 0, fec2 = 0, fec3 = 0, fec4 = 0;
// 客户端:使用异或操作生成冗余数据
void client(){
fec1 = a ^ b;
fec2 = b ^ c;
fec3 = c ^ d;
fec4 = d ^ a;
}
// 模拟网络丢包:这里简单的丢弃c、d、fec1、fec2这四个包
void loss_packet(){
c = 0;
d = 0;
fec1 = 0;
fec2 = 0;
}
// 服务器:通过冗余数据恢复出被丢失的数据
void server(){
d = fec4 ^ a;
c = fec3 ^ d;
}
int main(){
client();
loss_packet();
server();
fprintf(stdout,"a = %d, b = %d, c = %d, d = %d\n",a,b,c,d);
// 输出结果:a = 1, b = 2, c = 3, d = 4
return 0;
}