问题:

如何增量同步文件,例如一个文本文件有10M,分别存放在A,B两个地方,现在两个文件是完全一样的,但是我马上要在A上对这个文件进行修改,B如何实现自动和A上的文件保持一致,并且网络的传输量最少。

应用场景:

这样的使用场景太多,这里随便列举几个

1.A机器为线上运营的机器,现在需要一台备份的机器B,当A发生宕机的时候,或者硬盘损坏等各种认为非人为原因导致数据不可用时,可以很快从B恢复

2.SVN这样的应用场景,不需要每次修改都向服务器发送并替换掉一个文件,而是只发送被修改的部分

3.手机客户端对一个文本修改,如果那个文本有2M,难道我每次更新都需要上传整个文件吗?每次2M,傻子才用!

等等....

解决方案:

.分而治之

计算机最重要的基本算法思路就是分而治之,在我们眼里,一个文件不是一个文件,而是一堆存储块,每个存储块可能20Byte大小,至于这个值具体多大,你可以自己设定,这里的20Byte仅提供参考。通过这样的方法,一个文件被分成了很多个块,我们只需要比对块是否相同就可以得出哪个部分做了相应修改。

.快速校验

刚上面提到如何比对文件,当然这里肯定不会把文件的每个块上传去比对,那样做就没有意义了。快速比对这不禁让我想起了哈希规则,哈希表可以通过O(1)的复杂度查找某个key,为什么?  因为它通过计算hash值来初步验证key,一个key的hash值是唯一的。但是仅仅验证hash值是不可靠的,因为hash值有可能会冲突,所以在验证完hash值后,我们在进行key的比较来确定要找的值...

通过哈希的思路,我们可以使用类似的方法来实现文件增量同步,把每一个存储块,通过MD5计算其值,然后传递MD5值到服务器,让服务器比对MD5来确定有没有被修改,如若MD5值不相等,则判定这个文件块有被修改过

为什么是MD5?

1)能够将任意长度的字符串转换为128位定长字符串(MD5 16)

2)MD5能够保证绝大部分情况下不同的值hash之后其hash值不一样,哈希冲突比较少

这样就可以了吗?

No,MD5的生成需要占用比较长的CPU时间,所以我们需要寻找一种更简洁的校验方式,这里选用Alder32 是一个比较通用的解决方案

Alder32有两个优点: 
1、计算非常快,比MD5快多了,成本小;
2、当我们有了从0-k长度的校验和后,计算出1-k或者2-k等其他校验和非常方便,只要少量运算即可。(k可以理解为上面的20Byte)

当然,它的缺点也很明显,就是碰撞率比MD5高多了,所以,我们客户端需要同时计算出Alder32校验和与MD5值,传给服务器,而服务器,为了节省CPU时间,第一步只生成Alder32进行校验,当值相等时,在进行MD5校验,这样服务器就节省了很大的开支。

Alder32算法实现:


 A = 1 + D1 + D2 + ... + Dn (mod 65521)
 B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521)
   = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n (mod 65521)

Adler-32(D) = B × 65536 + A

C实现版本

const int MOD_ADLER = 65521;
 
unsigned long adler32(unsigned char *data, int len) /* where data is the location of the data in physical memory and 
                                                       len is the length of the data in bytes */
{
    unsigned long a = 1, b = 0;
    int index;
 
    /* Process each byte of the data in order */
    for (index = 0; index < len; ++index)
    {
        a = (a + data[index]) % MOD_ADLER;
        b = (b + a) % MOD_ADLER;
    }
 
    return (b << 16) | a;
}

三.实现更改

因为已经找出来了文件不同的地方,所以只需要按需上传更改的部分到服务器,然后服务器做更改就可以了。

实例分析:

理论概述完毕,来点小例子子

客户端文件内容是:

taohuiissoman

而服务器的文件内容是:

itaohuiamsoman

首先,客户端开始分块并计算出MD5和Alder32值。

如上图,像taoh是一块,对taoh分别计算出MD5和alder32值。以此类推,最后一个n字母不足4位保留。于是,客户端把计算出的MD5和alder32按顺序发出,最后发出字符n。

服务器收到后,先把自己保存的File.2的内容按4字节划分。

划分出itao、huia、msom、an,当然,这些串的Alder32值肯定无法从File.1里划分出的:taoh、uiis、soma、n找出相同的。于是向后移一个字节,从t开始继续按4字节划分。

从taoh上找到了alder32相同的块,接着再比较MD5值,也相同!于是记下来,跳过taoh这4个字符,看uiam,又找不到File.1上相同的块了。继续向后跳1个字节从i开始看。还是没有找到Alder32相同,继续向后移,以此类推。

到了soma,又找到相同的块了。

重复上面的步骤,直到File.2文件结束。

通过这个简单的例子,可以设想一下其他任何的增删查改功能 

参考资料:http://cs.anu.edu.au/techreports/1996/TR-CS-96-05.pdf


博客地址:Zealot Yin

欢迎转载,转载请注明出处[http://creator.cnblogs.com/]

如何实现文件增量同步——算法相关推荐

  1. linux 实现文件增量同步

    rsync + Sersync 实现增量同步 需求:同步服务器数据到本地 环境:已配置openvpn 让服务器与本地服务器可以处在同一网络环境 服务器:客户端(192.168.0.67) 服务端(19 ...

  2. rsync文件实时同步_从文件同步rsync算法谈起

    之前在某个产品中使用了Gossip算法进行数据库数据的同步,但是在新的产品中有个需求,就是当文件变化时,(由于文件比较大,比较多)支持增量推送到文件服务器上.于是想到了Unix下的rsync算法,本文 ...

  3. linux rsync文件夹增量同步

    就是说用rsync去同步一个很大的文件夹几十G,第一次的时候会同步几十G的数据,然后又更新/删除的时候只需要同步跟新.删除的文件)用的是xxx算法,这不是我们需要管的,大多说情况我们需要知道怎么用就行 ...

  4. python实现文件夹增量同步

    工作中,经常要把windows的文件夹同步到linux上.xftp也可以,sublime也有远程上传的插件,但没找到支持增量的...大量时间花在找插件,装环境...然后一怒之下,自己东拼西凑了一下. ...

  5. 群晖增量同步Linux文件夹,用自定义脚本实现群晖NAS中本地文件夹之间的增量同步复制...

    用自定义脚本实现群晖NAS中本地文件夹之间的增量同步复制 2021-02-21 15:39:44 60点赞 646收藏 52评论 使用情景:群晖DS918+,两块12T RAID1存重要数据,1块2T ...

  6. rsync+inotify实现文件增量实时同步

    rsync+inotify实现文件增量实时同步 项目环境 防火墙{项目环境,不是必要条件} 项目需求 一.rsync安装部署 1.检查是否安装rsync 2.测试系统rsync命令 3.新建配置文件 ...

  7. Apache NIFI 安装 ● 操作 ● 文件同步 ● oracle 数据库增量同步实例讲解

    nifi简介 nifi背景 NiFi之前是在美国国家安全局(NSA)开发和使用了8年的一个可视化.可定制的数据集成产品.2014年NSA将其贡献给了Apache开源社区,2015年7月成功成为Apac ...

  8. DataX以及增量同步

    目录 第一部分:DataX 一.DataX基本知识 二.DataX应用 三.DataX安装测试 四.DataX性能调优 五.DataX源码编译问题整理 六.datax增量同步 第二部分:增量同步 一. ...

  9. SpringBoot + xxl-job 多数据源异构数据增量同步

    SpringBoot + xxl-job 多数据源异构数据增量同步 文章目录 SpringBoot + xxl-job 多数据源异构数据增量同步 一.概述 二.实现步骤 2.1 项目搭建 2.2 接口 ...

最新文章

  1. p6安装后怎么连接oracle的数据库,p6-oraclexe数据库连接不上处理方法内部版20151012.doc...
  2. 转:软件设计漫谈之三:30分钟掌握面向对象类的设计原则
  3. 数据结构于算法—线性表
  4. access开发精要(12)-文本 和 备注 数据类型格式(1)
  5. 【论文解读】OneNet:一阶段的端到端物体检测器,无需NMS
  6. IDEA-2020版本 Gradle项目控制台输出乱码
  7. 33个热门数据分析软件,你都用过哪些?
  8. forward和redirect区别
  9. mysql设置用户永不过期_在Navicat Premium中管理MySQL用户 - 第2部分:创建新用户
  10. c++函数不允许递归_面试算法题:不会递归函数被面试官刷了下来!
  11. 【SQL】日期型函数
  12. Tesseract-OCR识别中文与训练字库实例
  13. oracle 平均值 最大值,Oracle分析函数三——SUM,AVG,MIN,MAX,COUNT
  14. 洛谷 U87052 一线天
  15. 新一代超低功耗STM32U5,到底有啥亮点?
  16. Exoplayer的详细使用UI篇
  17. ubuntu 下的开机启动项管理命令
  18. Minecraft基岩版电脑端游戏按键整合
  19. 2021年森林督查暨森林资源管理“一张图”更新工作方案
  20. java jpanel 层,java – 循环遍历JPanel

热门文章

  1. nginx在linux下是服务吗,[Linux]如何给Nginx添加服务
  2. Caffe RPN :error C2220: warning treated as error - no 'object' file generated
  3. zookeeper leader选举机制
  4. Linux环境下安装RocketMQ(MetaQ)
  5. PHP 简单计算器代码实现
  6. 模型设计器工具控件LinqConnect
  7. POJ 1861 Network
  8. Android---- 获取当前应用的版本号和当前android系统的版本号
  9. 远程桌面mstsc命令参数的使用
  10. 安装VS 2008 EXPRESS出现无法读取deffactory.dat错误