一、什么是Rsync

1、rsync 是 unix / linux 下同步文件的一个高效算法,它能同步更新两处计算机的文件和目录,并适当的利用查找文件中的不同块以减少数据传输。
2、rsync中一项与其他大部分类似程序或协定中所未见的重要特性是镜像是只对有变更的部分进行传送
3、rsync 可拷贝 / 显示目录属性,以及拷贝文件,并可选择性的压缩以及递归拷贝。

二、产生的起因

1 、rsync想要解决的问题是当我们要同步的文件只想传不同的部分,就需要对两边的文件做Diff算法,但是这两个问题在两台机器上,所以无法去做Diff算法。如果我们要做Diff,就要把一个文件传到另一个机器做Diff,但这样一来,我们就传了整个文件,这与我们只想传文件的不同部分的初衷有所违背。 而rsync算法就是要解决这个问题

三、Rsync算法

rsync的算法假设如下:(假设有两个同源文件fileOne,同步的目的文件是fileTwo
1、首先,我们将把fileTwo的文件平均切分成若干小块,比如每块512个字节(最后一块会小于这个数),然后对每块计算两个checksum

  • 一个叫rolling checksum,是弱checksum,32位的checksum,其使用的是Adler-32校验算法,
  • 另一个是强checksum,128位的,而之前用md4,现在所用的md5 hash算法。

2、CheckSum算法:同步目标端会吧fileTwo的一个checksum列表传给同步源,这个列表里包括了三个东西,rolling checksum(32bits),md5 checksum(128bits),文件块编号

3、checksum查找算法:同步源端拿到fileTwo的checksum数组后,会把这个数据存到一个hash table中,用rolling checksum做hash,以便获得O(1)时间复杂度的查找性能。这个hash table是16bits的,所以 hash table的尺寸是2^16 次,对rolling checksum的hash会被散列到0 - 2^16 - 1 中的某个值

4、比对算法

  • 取fileOne的第一个文件块(假设具有512个长度),也就是从fileOne的第1个字节到第512个字节,取出来后做rolling checksum计算。计算好的值到hash表中查
  • 如果查到了这个值,就说明发现在fileTwo中潜在相同的文件块,紧接着就比较md5的checksum,因为 rolling checksum太弱,可能会发生碰撞。于是还要算md5的128bits的checksum,这样一来我们就有了2^-(32+128) = 2^-160的概率发生碰撞,因为概率太小,可以进行忽略。如果rolling checksum和md5 checksum都相同,这说明在fileTow中具有相同的块,我们就只需要记下这一块在fileTwo下的文件编号。
  • 如果fileOne的rolling checksum 没有在hash table中找到,那就不用算md5 checksum了。表示这一块有不同的信息。总之只要rolling checksum 或md5 checksum其中一个在fileTow的checksum hash表中找不到匹配项,那么就会触发算法对fileTow的rolling动作。算法就会往后step 1 个字节,取fileOne中字节2-513的文件块要做checksum
  • 这样就可以找出fileOne相邻两次匹配中的那些文本字符,这些就是我们要往同步目标端传的文件内容

图示

rsync线程 rsync原理_数组


这样,最终,在同步源这端,我们的rsync算法可能会得到下面这个样子的一个数据数组,图中,红色块表示在目标端已匹配上,不用传输(注:我专门在其中显示了两块chunk #5),而白色的地方就是需要传输的内容(注意:这些白色的块是不定长的),这样,同步源这端把这个数组(白色的就是实际内容,红色的就放一个标号)压缩传到目的端,在目的端的rsync会根据这个表重新生成文件,这样,同步完成。

rsync线程 rsync原理_hash表_02


最后想说一下,对于某些压缩文件使用rsync传输可能会传得更多,因为被压缩后的文件可能会非常的不同。对此,对于gzip和bzip2这样的命令,记得开启 “rsyncalbe” 模式。