linux提供了rsync命令用于同步两台计算机中某个文件。
假设我们有一个文件20M,客户端与服务端都有一份。在某个时刻服务端文件变了,这时需要同步到客户端。
同步整个文件,显然不是最好的方法,并且如果网络慢,则情况会更加糟糕 。
理想情况下是只希望同步改变的文件块。
linux rsync的目的就是只同步改变了的文件块。
算法如下:
服务端与客户端,约定文件块大小。这里假设是1K。客户端将要同步的文件,分成若干块,最后一个不満1k的也为一个块。
对客户端文件的每个生成:一个弱校验(将1k数据映射到32位整数上),一个强检验(128位,MD5算法)。
这里如果两个块不同,则生成的校验值有可能相同(映射空间有限)。而如果校验值不同,则块肯定不同。
这时,客户端将文件每个块的弱,强检验列表传到服务端。
服务端,将这个列表,存入到一个map,以弱检验为key,强检验为value。
然后服务端文件,从0字节开始到1023计算出弱检验值。分以下两个情况:
如果相同,则查找map,找出强检验值,如果与客户端的这块强检验值还相等。则表明是同一个块,不
需要再传送这个块。
如果不相同,则表明当前服务端这个块被更改过。这时从1到1024继续执行上面的步聚。
注:不足一个块的数据,不需要再比较 可直接传送。
举例:
4字节为一个块
假设客户端文件内容如下:
abcdefghu
服务端文件内容如下:
tabcdgefghu
这时客户端传给服务端校验列表:
MD5(abcd)+Addr32(abcd)
MD5(efgh)+Addr32(efgh)
服务端,开始计算 tabc的弱检验码,从Map中取以这个弱检验为key的值。发现没有,这时表明块不一致,则跳过一个字节。
从a开始计算abcd的弱检验码,存在,继续比较强检验码,还是相同,这时将abcd块标为相同,表明不需要同步。
接着计算gefg,找不到,则跳过一个字节。计算efgh。这时找到,并且强检验码也相同。标为不需要同步。
最后结果,跳过的t,g,u需要同步。