Rsync文件同步的核心算法

文章出处:http://coolshell.cn/articles/7425.html#more-7425

rsync是unix/linux下同步文件的一个高效算法,它能同步更新两处计算机的文件与目录,并适当利用查找文件中的不同块以减少数据传输。rsync中一项与其他大部分类似程序或协定中所未见的重要特性是镜像是只对有变更的部分进行传送。rsync可拷贝/显示目录属性,以及拷贝文件,并可选择性的压缩以及递归拷贝。rsync利用由Andrew Tridgell发明的算法。这里不介绍其使用方法,只介绍其核心算法。我们可以看到,Unix下的东西,一个命令,一个工具都有很多很精妙的东西,怎么学也学不完,这就是Unix的文化啊。

本来不想写这篇文章的,因为原先发现有很多中文blog都说了这个算法,但是看了一下,发现这些中文blog要么翻译国外文章翻译地非常烂,要么就是介绍这个算法介绍得很乱让人看不懂,还有错误,误人不浅,所以让我觉得有必要写篇rsync算法介绍的文章。(当然,我成文比较仓促,可能会有一些错误,请指正)

问题

首先, 我们先来想一下rsync要解决的问题,如果我们要同步的文件只想传不同的部分,我们就需要对两边的文件做diff,但是这两个问题在两台不同的机器上,无法做diff。如果我们做diff,就要把一个文件传到另一台机器上做diff,但这样一来,我们就传了整个文件,这与我们只想传输不同部的初衷相背。

于是我们就要想一个办法,让这两边的文件见不到面,但还能知道它们间有什么不同。这就出现了rsync的算法。

算法

rsync的算法如下:(假设我们同步源文件名为fileSrc,同步目的文件叫fileDst

1)分块Checksum算法。首先,我们会把fileDst的文件平均切分成若干个小块,比如每块512个字节(最后一块会小于这个数),然后对每块计算两个checksum,

  • 一个叫rolling checksum,是弱checksum,32位的checksum,其使用的是Mark Adler发明的adler-32算法,
  • 另一个是强checksum,128位的,以前用md4,现在用md5 hash算法。

为什么要这样?因为若干年前的硬件上跑md4的算法太慢了,所以,我们需要一个快算法来鉴别文件块的不同,但是弱的adler32算法碰撞概率太高了,所以我们还要引入强的checksum算法以保证两文件块是相同的。也就是说,弱的checksum是用来区别不同,而强的是用来确认相同。(checksum的具体公式可以参看这篇文章

2)传输算法。同步目标端会把fileDst的一个checksum列表传给同步源,这个列表里包括了三个东西,rolling checksum(32bits)md5 checksume(128bits)文件块编号

我估计你猜到了同步源机器拿到了这个列表后,会对fileSrc做同样的checksum,然后和fileDst的checksum做对比,这样就知道哪些文件块改变了。

但是,聪明的你一定会有以下两个疑问:

  • 如果我fileSrc这边在文件中间加了一个字符,这样后面的文件块都会位移一个字符,这样就完全和fileDst这边的不一样了,但理论上来说,我应该只需要传一个字符就好了。这个怎么解决?
  • 如果这个checksum列表特别长,而我的两边的相同的文件块可能并不是一样的顺序,那就需要查找,线性的查找起来应该特别慢吧。这个怎么解决?

很好,让我们来看一下同步源端的算法。

3)checksum查找算法。同步源端拿到fileDst的checksum数组后,会把这个数据存到一个hash table中,用rolling checksum做hash,以便获得O(1)时间复杂度的查找性能。这个hash table是16bits的,所以,hash table的尺寸是2的16次方,对rolling checksum的hash会被散列到0 到 2^16 – 1中的某个整数值。(对于hash table,如果你不清楚,建议回去看大学时的数据结构教科书)

顺便说一下,我在网上看到很多文章说,“要对rolling checksum做排序”(比如这篇这篇),这两篇文章都引用并翻译了原作者的这篇文章,但是他们都理解错了,不是排序,就只是把fileDst的checksum数据,按rolling checksum做存到2^16的hash table中,当然会发生碰撞,把碰撞的做成一个链表就好了。这就是原文中所说的第二步——搜索有碰撞的情况。

4)比对算法。这是最关键的算法,细节如下:

4.1)取fileSrc的第一个文件块(我们假设的是512个长度),也就是从fileSrc的第1个字节到第512个字节,取出来后做rolling checksum计算。计算好的值到hash表中查。

4.2)如果查到了,说明发现在fileDst中有潜在相同的文件块,于是就再比较md5的checksum,因为rolling checksume太弱了,可能发生碰撞。于是还要算md5的128bits的checksum,这样一来,我们就有 2^-(32+128) = 2^-160的概率发生碰撞,这太小了可以忽略。如果rolling checksum和md5 checksum都相同,这说明在fileDst中有相同的块,我们需要记下这一块在fileDst下的文件编号

4.3)如果fileSrc的rolling checksum 没有在hash table中找到,那就不用算md5 checksum了。表示这一块中有不同的信息。总之,只要rolling checksum 或 md5 checksum 其中有一个在fileDst的checksum hash表中找不到匹配项,那么就会触发算法对fileSrc的rolling动作。于是,算法会住后step 1个字节,取fileSrc中字节2-513的文件块要做checksum,go to (4.1) – 现在你明白什么叫rolling checksum了吧。

4.4)这样,我们就可以找出fileSrc相邻两次匹配中的那些文本字符,这些就是我们要往同步目标端传的文件内容了。

图示

怎么,你没看懂? 好吧,我送佛送上西,画个示意图给你看看(对图中的东西我就不再解释了)。

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

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

Rsync实现文件同步的算法(转载)的更多相关文章

  1. Linux Rsync实现文件同步备份(转载)

    原文地址:Linux Rsync实现文件同步备份作者:夷北 转自:http://www.mike.org.cn/blog/index.php?load=read&id=639###pp=0 [ ...

  2. rsync+inotify文件同步

    rsync+inotify文件同步 在服务器中,通常结合计划任务.shell脚本来执行本地备份.为了进一步提高备份的可靠性,使用异地备份也是非常重要的,利用rsync工具,可以实现快速.高效的异地备份 ...

  3. rsync+inotfiy文件同步

    rsync+inotfiy文件同步 1.部署rsync服务 yum install rsync #安装rsync,如果嫌yum版本过低也可以源码安装 2.vim /etc/rsyncd.conf #默 ...

  4. rsync+inotify文件同步 - 同步慢的问题

    rsync+inotify文件同步 - 同步慢的问题 我们来看网上的教程,我加了注释.(网上所有的教程基本都一模一样,尽管写法不一样,致命点都是一样的) #!/bin/bash /usr/bin/in ...

  5. Linux下简单粗暴使用rsync实现文件同步备份【转】

    这篇来说说如何安全的备份,还有一点不同的是上一篇是备份服务器拉取数据,这里要讲的是主服务器如何推送数据实现备份. 一.备份服务器配置rsync文件 vim /etc/rsyncd.conf #工作中指 ...

  6. inotify配合rsync实现文件同步

    一.slave端rsync设置在此部署rsync服务和rsync daemon 1.安装rsync   2.配置rsyncd.conf文件#vi /etc/rsyncd.conf配置文件uid = r ...

  7. CentOS安装和配置Rsync进行文件同步

    Liunx系统实现文件同步不需要搭建FTP这类的工具,只需要按照Rsync配置下文件就可以. 本文以Centos7.0为例. 1. 首先关闭SELINUX(不关闭无法同步,权限太高了) vi /etc ...

  8. centos7 使用rsync 实现文件同步

    一.服务端(192.168.8.81): 安装软件: yum -y install rsync 创建需同步的目录: mkdir -p /home/root/rsync 编辑配置文件:vim /etc/ ...

  9. Centos7利用rsync实现文件同步

    0x01 测试环境 CentOS 7.4 Rsync服务端:192.168.204.130 CentOS 7.4 Rsync客户端:192.168.204.168 0x02 rsync同步方式 第一种 ...

随机推荐

  1. ASP.NET MVC5 学习系列之初探MVC

    一.由问题看本质 (一)什么是MVC? MVC是Model-View-Controller的简称.它是在1970年引入的软件设计模式.MVC 模式强迫关注分离 — 域模型和控制器逻辑与UI是松耦合关系 ...

  2. 剑指offer:旋转数组的最小数字

    题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个 ...

  3. 22_IO_第22天(File、递归)_讲义

    今日内容介绍 1.File 2.递归 xmind:下载地址: 链接:https://pan.baidu.com/s/1Eaj9yP5i0x4PiJsZA4StQg 密码:845a 01IO技术概述 * ...

  4. iOS-UICollectionViewLayout方法介绍

    注意:UICollectionView的自定义功能就是自己去实现UICollectionViewLayout的子类,然后重写相应的方法来实现Cell的布局 1.当布局首次被加载时会调用prepareL ...

  5. js作用域相关笔记

    1.js引擎.编译器.作用域. 引擎:负责JS全过程的编译和执行: 编译器:负责语法分析和代码生成: 作用域:负责收集并维护声明组成的查询,以及当前执行代码对这些变量的访问权限(简言之,作用域就是用于 ...

  6. wpf后台设置颜色(背景色,前景色)

    有时候你是不是也会遇到要在wpf后台给某个控件设置背景色或者给文字设置前景色的情况? 本人最近看到一个从自定义的combobox读取系统字体和颜色的实例,该实例实现了随字体combobox选项改变而改 ...

  7. [转帖]Beyond Compare如何进行二进制比较

    Beyond Compare如何进行二进制比较 http://www.beyondcompare.cc/jiqiao/erjinzhi-bijiao.html 在使用Beyond Compare软件比 ...

  8. Two Sum III - Data structure design

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  9. poj 3254(状态压缩DP)

    poj  3254(状态压缩DP) 题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相 ...

  10. SpringBoot(六)_AOP统一处理请求

    什么是AOP AOP 是一种编程范式,与编程语言无关: 将通用逻辑从业务逻辑中分离出来(假如你的业务是一条线,我们不在业务线上写一行代码就能完成附加任务!我们会把代码写在其他的地方): 具体实现 (1 ...