Linux 文件实时同步:Sersync 介绍
Linux 2014-03-02 2852
  现对服务器数据实时同步的解决方案,其中 Inotify 用于监控 Sersync 所在服务器上文件系统的事件变化,而 Rsync 是目前广泛使用的本地以及异地数据同步工具,其优点是只对变化的目录数据操作,甚至是一个文件不同的部分进行同步,所以其优势大大超过使用挂接文件系统或 scp 等方式进行镜像同步。

  目前使用比较多的同步工具为 Inotify-tools 和 Openduckbill。Inotify-tools 我们之前做过介绍,这里就不做阐述。简单说下 Openduckbill,Openduckbill 也是 google 的一个开源项目,它也是依赖于inotif-tools,并且它 和 Inotify 都是基于脚本语言编写的,其设计思路同样是采用文件系统事件监控机制 Inotify 与 Rsync 命令来做设计架构的。这里在多说一点,有些朋友可能会在两台甚至多台服务器之间,互相搭建 Inotify-tools + Rsync 之类的同步部署来做互相同步,这个是很不推荐的,主要一方面就是在同步的文件时间戳上容易出问题,导致同步失败,甚至版本不同步。因此,如果你是要做互相同步,推荐使用 Csync。

  这里呢,就说说 Sersync 优于 Inotify-tools 和 Openduckbill 的地方吧!

  1、Sersync 使用 c++ 编写,对 linux 系统文件产生的临时文件和重复的文件操作会进行过滤,在本文后面会提到该点。使用 sersyc 和 rsync 结合做同步的时候,会大大减少运行时所消耗的本地以及网络资源,因此在速度方面有显著提升。

  2、相比 Inotify-tools 和 Openduckbill,Sersync 配置起来更为简单方便。在谷歌 Sersync 项目下载的安装包的 bin 目录下,放置了已经编译好的二进制文件,搭配 bin 目录下的xml文件可以直接部署使用。

  3、Sersync 采用多线程(默认10)进行同步(即可以并发同步多个不同文件),尤其是针对较大文件同步的时候,它能够保证多个服务器实时保持同步状态。

  4、Sersync 自带了出错处理机制。它可以通过失败队列自动对之前出错的文件进行重新同步操作。如果届时依旧失败,它会每 10 个小时对同步失败的文件再进行重新同步操作,直到文件同步为止。

  5、Sersync 自带有 crontab 功能,因此不需要借助系统的 crontab ,只需在 xml 配置文件中开启该功能,即可按预先的配置,每隔一段时间自动做一次整体同步操作。

  6、Sersync 还自带了 socket 与 refreshCDN 的协议扩展,可以满足有特殊需求的公司二次开发。(之前的版本有http扩展,目前已去除) 下面是,Sersync 的设计结构图:


  以上是 Sersync 谷歌项目组上面的设计结构图!现在可能是因为某些原因(你懂得),不能访问谷歌的页面,即使用某种方式出去也不能这个图片也是打不开状态了。本人之前珍藏的有,因此这里特把该图贴出,方便大家学习。

  鉴于,英文版本可能对广大博友带来阅读压力,下面特贴出中文翻译过的版本。


  针对上图的设计架构,这里做几点说明,来帮助大家阅读和理解该图:

  1、线程组线程是等待线程队列的守护线程,当事件队列中有事件产生的时候,线程组守护线程就会逐个唤醒同步线程。当队列中 Inotify 事件较多的时候,同步线程就会被全部唤醒一起工作。这样设计的目的是为了能够同时处理多个 Inotify 事件,从而提升服务器的并发同步能力。同步线程的最佳数量=核数 x 2 + 2。

  那么之所以称之为线程组线程,是因为每个线程在工作的时候,会根据服务器上新写入文件的数量去建立子线程,子线程可以保证所有的文件与各个服务器同时同步。当要同步的文件较大的时候,这样的设计可以保证每个远程服务器都可以同时获得需要同步的文件。

  2、服务线程的作用有三个:
    a、处理同步失败的文件,将这些文件再次同步,对于再次同步失败的文件会生成 rsync_fail_log.sh 脚本,记录失败的事件。
    b、每隔10个小时执行 rsync_fail_log.sh 脚本一次,同时清空脚本。
    c、crontab功能,可以每隔一定时间,将所有路径整体同步一次。

  3、过滤队列的建立是为了过滤短时间内产生的重复的inotify信息,例如在删除文件夹的时候,inotify就会同时产生删除文件夹里的文件与删除文件夹的事件,通过过滤队列,当删除文件夹事件产生的时候,会将之前加入队列的删除文件的事件全部过滤掉,这样只产生一条删除文件夹的事件,从而减轻了同步的负担。同时对于修改文件的操作的时候,会产生临时文件的重复操作。

  Ifnotify事件分析
  下面来用具体数据去做分析,来解释为什么 Sersync 比 Inotify-tools 和 Openduckbill 更优秀!

  首先来看一张图,这张图是从谷歌 Sersync 项目组的分析文档里面摘出来的,该图是对同一个文件做write and close操作的时候,产生的10个事件。



  为什么我们认为脚本监控效率低?
  由于我们执行复制,移动,新建,删除等操作时,会产生诸多事件。又上图来看他除了产生.开头的隐藏临时文件和~结尾的临时文件,还产生了3个4913的数字命名的临时文件(注意,在 write 文件的时候,总会产生这3个数字文件,除非write的文件名叫做4913时,才会产生别的数字命名的事件)。

  因此当我们使用脚本监控,即使通过使用 --exclude 这样的选项结合正则语法,也无法完美过滤掉一些文件系统产生的临时文件和临时事件,这样就造成了 rsync 的反复执行。即便你把“.”开头与“~”结尾的事件过滤了,对于test文件仍旧有3次操作,分别是8、64和256。

  补充:这里简单介绍下事件名称与对应代码。事件256代表create事件,事件8代表write_close事件,事件512代表remove事件,事件64是move_from事件,即将文件mv出当前路径时产生事件。事件128是move_to事件,即将其它路径的文件移入到当前路径。移出与移入操作可以通过cookie值来确定是否是同一文件。由此可见,当移动操作时候,是将 test 移动为 test~ ,其实是修改了名字,通过 cookie 可以看出,它们是对同一文件的操作。

  此时,我们 Sersync 的过滤队列效果就出来了!以下是过滤队列的三大作用!
  1、过滤队列的第一个作用
  按照如上的情形,如果通过过滤队列,就只会剩下一个 8 号事件,一定程度上也提高了同步的效率。

  2、过滤队列的第二个作用
  当你在本机删除目录的时候,假设你删除了一个包含 5 个文件的目录。Inotify 会产生 6 个事件出来,分别是 5 个文件删除事件和 1 个目录删除事件。如果使用过滤队列的话,正常情况下会只产生一个目录删除事件,这无疑大大减少了 Inotify 事件的产生,从而减少 Rsync 无谓的同步次数。当然,这里说的也不绝对。如果这 6 个事件分多次读到进入队列,那么可能还没来得及过滤,就已经被同步线程从队列中取走同步了,但是这确实在一定程度上减少了删除目录时的同步通信次数。

  3、过滤队列的第三个作用
  它可以过滤监控目录下的目录。如果我们不想同步目录下的某些目录或者一些后缀的文件,只需要在inotify启动的时候,remove 掉那些不需监控的子目录监控即可。对于不需要监控的子目录,产生的文件事件就会从载入同步队列前过滤掉。如果使用 Rsync 用 -exclude 参数虽然也可以实现过滤,但是还要与 Rsync 守护进程进行了一次交互才行。