一、rsync的优点与不足
 与传统的cp、tar备份方式相比,rsync具有安全性高、备份迅速、支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等。
 随着应用系统规模的不断扩大,对数据的安全性和可靠性也提出的更好的要求,rsync在高端业务系统中也逐渐暴露出了很多不足,首先,rsync同步数 据时,需要扫描所有文件后进行比对,进行差量传输。如果文件数量达到了百万甚至千万量级,扫描所有文件将是非常耗时的。而且正在发生变化的往往是其中很少 的一部分,这是非常低效的方式。其次,rsync不能实时的去监测、同步数据,虽然它可以通过linux守护进程的方式进行触发同步,但是两次触发动作一 定会有时间差,这样就导致了服务端和客户端数据可能出现不一致,无法在应用故障时完全的恢复数据。基于以上原因,rsync+inotify组合出现了!

二、 初识inotify
 Inotify 是一种强大的、细粒度的、异步的文件系统事件监控机制,linux内核从2.6.13起,加入了Inotify支持,通过Inotify可以监控文件系统 中添加、删除,修改、移动等各种细微事件,利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而inotify-tools就是这样 的一个第三方软件。
在上面章节中,我们讲到,rsync可以实现触发式的文件同步,但是通过crontab守护进程方式进行触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变动时,就触发rsync同步,这样刚好解决了同步数据的实时性问题。

三、 安装inotify工具inotify-tools
 由于inotify特性需要Linux内核的支持,在安装inotify-tools前要先确认Linux系统内核是否达到了 2.6.13以上,如果Linux内核低于2.6.13版本,就需要重新编译内核加入inotify的支持,也可以用如下方法判断,内核是否支持 inotify:

[root@localhost ~]# uname -r
2.6.32-279.el6.x86_64
[root@localhost ~]# ll /proc/sys/fs/inotify/
total 0
-rw-r--r-- 1 root root 0 Aug 30 21:00 max_queued_events
-rw-r--r-- 1 root root 0 Aug 30 21:00 max_user_instances
-rw-r--r-- 1 root root 0 Aug 30 21:00 max_user_watches

如果有上面三项输出,表示系统已经默认支持inotify,接着就可以开始安装inotify-tools了。
可以到http://inotify-tools.sourceforge.net/下载相应的inotify-tools版本,然后开始编译安装:

[root@localhost ~]# tar -zxvf inotify-tools-3.14.tar.gz 
[root@localhost ~]# cd inotify-tools-3.14
[root@localhost inotify-tools-3.14]# ./configure 
[root@localhost inotify-tools-3.14]# make && make install
[root@localhost ~]# ll /usr/local/bin/
total 88
-rwxr-xr-x. 1 root root 44319 Aug 30 21:40 inotifywait
-rwxr-xr-x. 1 root root 41409 Aug 30 21:40 inotifywatch
[root@localhost ~]#

inotify-tools安装完成后,会生成inotifywait和inotifywatch两个指令,其中,inotifywait用于等待文件或文件集上的一个特定事件,它可以监控任何文件和目录设置,并且可以递归地监控整个目录树。
inotifywatch用于收集被监控的文件系统统计数据,包括每个inotify事件发生多少次等信息。

四、 inotify相关参数
inotify定义了下列的接口参数,可以用来限制inotify消耗kernel memory的大小。由于这些参数都是内存参数,因此,可以根据应用需求,实时的调节其大小。下面分别做简单介绍。
    /proc/sys/fs/inotify/max_queued_evnets    
       表示调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,超出这个值的事件被丢弃,但会触发IN_Q_OVERFLOW事件。
    /proc/sys/fs/inotify/max_user_instances
        表示每一个real user ID可创建的inotify instatnces的数量上限。
    /proc/sys/fs/inotify/max_user_watches
        表示每个inotify instatnces可监控的最大目录数量。如果监控的文件数目巨大,需要根据情况,适当增加此值的大小,例如:
echo 30000000 > /proc/sys/fs/inotify/max_user_watches

五、 inotifywait相关参数
Inotifywait是一个监控等待事件,可以配合shell脚本使用它,下面介绍一下常用的一些参数:
-m, 即--monitor,表示始终保持事件监听状态。
-r, 即--recursive,表示递归查询目录。
-q, 即--quiet,表示打印出监控事件。
-e, 即--event,通过此参数可以指定要监控的事件,常见的事件有modify、delete、create、attrib等。
更详细的请参看man  inotifywait。

六、 rsync+inotify示例

1、安装rsync与inotify-tools
inotify-tools是用来监控文件系统变化的工具,因此必须安装在内容发布节点,服务节点无需安装
内容发布节点(即server)充当了rsync客户端的角色,而服务节点充当了rsync服务器端的角色,整个数据同步的过程,其实就是一个从客户端向服务端推送数据的过程。这点与上面我们讲述的案例刚好相反。

2、服务节点配置rsync
 这里给出三个服务节点的rsync配置文件,以供参考,读者可根据实际情况自行修改。
服务节点rsyncd.conf配置如下

[root@localhost ~]# vim /etc/rsyncd.conf  #此文件需手动创建
uid = nobody
gid = nobody
use chroot = no
max connections = 10
stric mode = yes
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
[web1]
path = /mnt/share
comment = web1 file
ignore errors
read only = no
write only = no
hosts allow = 192.168.1.30
hosts deny = *
list = false
uid = root
gid = root
auth users = liang
secrets file = /etc/web1.pass
[root@localhost ~]# echo "/usr/bin/rsync --daemon" >>/etc/rc.local  #开机启动服务
[root@localhost ~]# echo "liang:123456" > /etc/web1.pass 
[root@localhost ~]# chmod 600 /etc/web1.pass

3、内容发布节点同步测试。

[root@localhost ~]# echo "123456" > /mnt/temp.pass
[root@localhost ~]# chmod 600 /mnt/temp.pass 
[root@localhost ~]# rsync -avH --delete --progress --password-file=/mnt/temp.pass /tmp liang@192.168.1.32::web1

4、编写rsync+inotify实时同步脚本

[root@localhost ~]# vim inotifyrsync.sh 
#!/bin/bash
host=192.168.1.32
srcdir=/web/www/
dst_rsync_module=web1
user=liang
/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $srcdir \
|while read files
        do
        /usr/bin/rsync -avzP --delete --progress --password-file=/mnt/temp.pass $srcdir $user@$host::$dst_rsync_module &> /dev/null
        echo "${files} was rsynced" >> /tmp/rsync.log 2>&1
        done

脚本相关解释如下:
--timefmt:指定日志时间的输出格式。
--format:指定变化文件的详细信息。
这两个参数一般配合使用,通过指定输出格式,输出类似与:
15/04/10 00:29 /web/wwwroot/ixdba.shDELETE,ISDIR was rsynced
15/04/10 00:30 /web/wwwroot/index.htmlMODIFY was rsynced
15/04/10 00:31 /web/wwwroot/pcre-8.02.tar.gzCREATE was rsynced
这个脚本的作用就是通过inotify监控文件目录的变化,进而触发rsync进行同步操作,由于这个过程是一种主动触发操作,通过系统内核完成的,所以,比起那些遍历整个目录的扫描方式,效率要高很多。
有时会遇到这样的情况:向inotify监控的目录(这里是/web/wwwroot/)写入一个很大文件时,由于写入这个大文件需要一段时间,此时 inotify就会持续不停的输出该文件被更新的信息, 这样就会持续不停的触发rsync去执行同步操作,占用了大量系统资源,那么针对这种情况,最理想的做法是等待文件写完后再去触发rsync同步。 在这种情况下,可以修改inotify的监控事件,即:“-e close_write,delete,create,attrib”。

[root@localhost www]# bash inotifyrsync.sh &  #把脚本放到后台执行
[root@localhost www]# echo "/web/www/inotifyrsync.sh &" >> /etc/rc.local  #开机启动