rsync是unix系统下很强大的同步工具,可以将源文件或者目录同步到目标文件或目录。与简单的scp相比,rsync具有传输速度快,高效的特点。借助其核心的差分算法,rsync可以实现最小化传输,即只传输变动的部分。
澳大利亚程序员AndrewTridgell为了寻找一种在并行系统之间传递数据的工具,设计和实现了rsync程序,官网地址为http://rsync.samba.org/。
讨论前的假设
为了便于讨论,假设我们要同步机子A上面的文件a到机子B上面的文件b。RSync程序将完成如下步骤来最小化同步的文件大小。
计算目标文件的摘要
首先计算目标文件的摘要的目的是将文件b同文件a比较,在机子A上面计算出其不同的部分,然后再进行传输。RSync是针对高可靠性,低传输率的网络环境。因此与其传输整个文件b,不如改成传输文件b的摘要来的划算。
RSync使用两个摘要算法来计算文件的摘要,一个弱摘要算法,Alder32;一个是强摘要算法,现在一般是MD5。使用两个摘要的原因,下面将会讨论到。步骤如下:
-
将文件b分成大小为S字节的字节块数组。
-
计算每个块的Alder32摘要和MD5摘要。
-
将如下格式的摘要数据传送到机子A:((块编号,Alder32摘要,MD5摘要),...
文件比较
A拿到文件b的摘要后,就要计算出文件a和文件b的不同。更具体的问题就是b的哪些字节块已经存在于a中?这样,RSync只需要向B传输那些新增加的字节块就好了。很容易想到,一般的实现如下:
-
计算文件a每个字节开始的大小为S的字节块摘要。
-
将a的每个块摘要和b的摘要数据比较。
-
将b中不存在的块以明文的形式传输到B上。
容易看出,上述算法的效率很低。一旦文件很大,所需的时间还不如直接用scp拷贝呢。
为了提供时间效率,Andrew利用哈希表对上面的算法进行加速。
哈希表的构造
假设哈希表的大小为H,一般都小于摘要算法的值空间。RSync具体实现中会使用16位大小的哈希表。其关键字就是文件块的弱摘要,对于冲突的块,则使用链表将其强摘要值记录下来。这正是Andrew天才的地方,如果只使用一种摘要算法,就会面临诸多性能问题:
-
仅使用弱摘要算法。则块冲突太多,要在链表中用字符串比较来查找相同的块。
-
仅使用强摘要算法。则计算文件a的摘要是面临巨大的计算量。
而先只计算文件a的弱摘要,只有在冲突的情况下才计算块的强摘要,可以很好地减少计算量,同时降低冲突时的查找代价。
比较算法
借助哈希表,算法的实现如下:
-
从第一个字节开始
-
计算字节块的弱摘要
-
查找哈希表,如果找到存在项,则进一步计算其强摘要
-
在冲突链表中找到块编号。
-
将字节偏移量加上S,返回上层步骤2
-
-
如果不存在,则返回改块。返回格式为(...,存在块编号,...,不存在块值,...)会
重构新文件
B获得A传回的数据后,只要遍历一遍差异数据,如果是存在块编号i,则读入b的字节块i;如果是不存在块E,则从差异化数据中读入E。这样新的文件就能快速构造出来,从而替换就文件。
块大小S的选取
从上面的描述可以看出:
-
S越大,B传给A的摘要数据就越小
-
S越小,A传给B的差异化数据就越小
下面是Andrew的实验数据图:
可以看到,块大小选择在5000到6000之间较为合理。很多文章说RSync的默认块大小为512,这个不完全正确。现在的RSync已经可以根据实际文件的大小自动选择。
rsync是一种在Unix系统中用于同步文件和目录的强大工具,以其高效的差分算法著称,只传输文件变动的部分。文章详细介绍了rsync的实现算法,包括计算目标文件摘要、文件比较、哈希表构造、比较算法以及重构新文件的过程,揭示了其在低传输率环境下保证速度和可靠性的秘诀。通过选择合适的块大小S,rsync可以在保持传输效率的同时减少数据传输量。
640

被折叠的 条评论
为什么被折叠?



