一.实时同步简介
1.什么是实时同步, 只要当前目录发生变化则会触发一个事件,事件触发后将变化的目录同步至远程服务器。
2.为什么要实时同步, 保证数据的连续性, 减少人力维护成本, 解决nfs等单点故障
3.实时同步实现原理, 实时同步需要借助 Inotify通知接口,用来监控目录的变化,如果监控的目录发生变更。则触发动作,这个动作可以是进行一次同步操作,或其他操作。
4.实时同步工具选择, 有sersync、lsync、inotify+rsync,通常我们会选择 sersyn或lsync。
二.如何实现实时备份
之前已经介绍了全网备份,具体可以参考链接文档:https://www.jianshu.com/p/b0157e4ab801
这样设置的全网备份是已经可以完成一个远程容灾备份的系统,但是这样的方案是存在很大的缺陷,由于rsync需要通过触发才能将客户端的数据推送到服务端,而触发则是通过定时任务来完成的,因此在两次触发同步操作的时间间隔内,服务端的数据与客户端的数据出现了不一致。如果在这个时间间隔内,网站系统出现了问题,也就意味着数据会出现丢失情况,因此,通过这种方式搭建的容灾系统在网站出现故障时是不能完全恢复的。
那么对于数据安全极高的业务系统,如何才能做到服务端和客户端数据实时同步呢?随着Linux版本的更新,在Linux2.6.13以后的内核提供了inotify文件系统监控机制,通过rsync与inotify的组合使用,完全可以实现rsync服务端和客户端数据的实时同步。
三.场景规划以及地址分配
这里当客户端的数据发生变化时实时将数据推送到备份服务器端。
四.通过rsync+inotify实现数据实时备份
1.rsync的优点与不足
1)优点:与传统命令备份(tar、cp...)相比,rsync具有安全性高、备份迅速、支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份的需求,例如,定期备份服务器的数据到远端服务器,对本地磁盘数据进行数据镜像等。
2)缺点:对于数据安全性要求更高的需求,rsync就会出现很多不足的情况。
①rsync同步数据时,需要扫描所有的文件进行对比后再进行差量传输,如果文件数量达上万级别或者更多时,扫描文件就需要消耗很长的时间,而更新或者新产生的数据往往就只是很少的一部分,这样就导致了效率低下的问题。
②rsync本身是不具备实时监测,同步数据的功能,虽然可以通设置定时任务结合rsync的守护进程的工作模式来实现数据同步,但是会出现时间间隔内出现故障导致数据不一致的情况,出现故障时就会出现无法完全恢复数据的情况。
2.inotify简介
inotify是一种强大的、细粒度的、异步的文件系统时间监控机制,linux内核从2.16.13版本开始,加入了对inotify的支持。通过inotify可以监控文件系统中添加、删除、修改、移动等各种各种细微的事件,利于这个内核的接口,第三方软件就可以监控文件的各种变化情况。inotify-tools就是这样一个第三方工具。
3.intofy的优点与不足
1)优点:可以监控文件系统事件变化
2)缺点:
①并发如果大于200个文件(10-100k),同步就会有延迟
②前面的脚本,每次全部推送一次,也可以实现值同步变化的数据,效率低下
③监控到事件后,调用rsync同步是单进程
④写脚本实现实时同步健壮性不高
4.部署inotify
1.检查系统内核版本是否支持
由于inotify是需要linux内核支持才可以使用,如果内核低于2.6.13版本,就需要重新编译内核加入inotify的支持。
[root@nfs ~]# uname -r
3.10.0-957.el7.x86_64
2.安装inotify
[root@nfs ~]# yum -y install inotify-tools
安装完成inotify-tools后,会生成inotifywait和inotifywatch两个指令
#inotifywait用于等待文件或文件集上的一个特定事件,可以监控任何文件和目录设置,并且可以递归地监控整个目录树。
#inotifywachey用于收集被监控的文件系统统计数据,包括每个inotify事件发生多少次等信息。
3.inotify参数说明
inotifywait详细参数说明
-e :--event的各种事件含义
4.命令测试
[root@nfs ~]# /usr/bin/inotifywait -mrq --format '%w %f' -e create,delete, attrib, close_ write /backup
5.编写脚本实现
#!/bin/bash
backup_Server=172.16.1.41
/usr/bin/inotifywait -mrq --format '%w%f' -e create,close_write,delete /data | while read line
do
cd /data
rsync -az ./ --delete rsync_backup@$backup_Server::nfsbackup --password-file=/etc/rsync.password
done
提示:上面这个脚本效率很低,效率低的原因在于只要目录出现变化都会导致整个目录下的东西都被推送一遍。因此,可以参考一下以下的脚本。
#!/bin/bash
Path=/data
backup_Server=172.16.1.41
/usr/bin/inotifywait -mrq --format '%w%f' -e create,close_write,delete /data | while read line
do
if [ -f $line ];then
rsync -az $line --delete rsync_backup@$backup_Server::nfsbackup --password-file=/etc/rsync.password
else
cd $Path &&\
rsync -az ./ --delete rsync_backup@$backup_Server::nfsbackup --password-file=/etc/rsync.password
fi
done
说明:以上的方案目前不在使用或者说使用的比较少,以上脚本是已经检验过的,你可以根据需求自行修改就可以了。
五.sersync介绍与使用
1.sersyc简介
sersync是国人基于rsync+inotify-tools开发的工具,不仅保留了优点同时还强化了实时监控,文件过滤,简化配置等功能,帮助用户提高运行效率,节省时间和网络资源。sersync项目地址 :https://github.com/wsgzao/sersync
2.serync的优点
1.sersync是使用c++编写,而且对linux系统文件系统产生的临时文件和重复的文件操作进行过滤(详细见附录,这个过滤脚本程序没有实现),所以结合rsync同步的时候,节省了运行时耗和网络资源,因此更快
2.相比较上面两个项目,sersync配置起来很简单,其中bin目录下已经有基本上静态编译的2进制文件,配合bin目录下的xml配置文件直接使用即可.
3.另外本项目相比较其他脚本开源项目,使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器保持同步状态
4.本项目有出错处理机制,通过失败队列对出错的文件重新同步,如果仍旧失败,则每10个小时对同步失败的文件重新同步
5.本项目自带crontab功能,只需在xml配置文件中开启,即可按照您的要求,隔一段时间整体同步一次,无须在额外配置crontab功能
6.本项目socket与http插件拓展,满足您二次开发的需要。
3.sersync部署实践
说明:这里环境与之前一样,这里不再重复配置rsync服务,如果这里不会配置请参照这个链接进行操作配置:https://www.jianshu.com/p/b0157e4ab801
1)安装sersync
#创建工具下载保存目录并下载sersync
[root@nfs ~]# mkdir /server/tools -p
[root@nfs ~]# cd /server/tools
[root@nfs /server/tools]# wget http://down.whsir.com/downloads/sersync2.5.4_64bit_binary_stable_final.tar.gz
#解压并将GNU-Linux-x86/移动到/usr/local/sersync
[root@nfs /server/tools]# tar zxf sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@nfs /server/tools]# ls
GNU-Linux-x86 sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@nfs /server/tools]# mv GNU-Linux-x86/ /usr/local/sersync
[root@nfs /server/tools]# cd /usr/local/sersync/
[root@nfs /usr/local/sersync]# ls
confxml.xml sersync2
2)配置sersync
#备份默认的配置文件
[root@nfs /usr/local/sersync]# cp confxml.xml confxml.xml.bak
#修改配置文件
[root@nfs /usr/local/sersync]# vim confxml.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<head version="2.5">
<host hostip="localhost" port="8008"></host>
<debug start="false"/>
<fileSystem xfs="true"/><!-- 文件系统 -->
<filter start="false"><!-- -->
<exclude expression="(.*)\.svn"></exclude>
<exclude expression="(.*)\.gz"></exclude>
<exclude expression="^info/*"></exclude>
<exclude expression="^static/*"></exclude>
</filter>
<inotify><!-- 监控的事件类型 -->
<delete start="true"/>
<createFolder start="true"/>
<createFile start="true"/>
<closeWrite start="true"/>
<moveFrom start="true"/>
<moveTo start="true"/>
<attrib start="false"/>
<modify start="false"/>
</inotify>
<sersync>
<localpath watch="/data"><!-- 监控的目录 -->
<remote ip="172.16.1.41" name="backup"/><!-- 主机名为backup的服务器的内网ip以及配置的rsync的模块名 -->
<!--<remote ip="192.168.8.39" name="tongbu"/>-->
<!--<remote ip="192.168.8.40" name="tongbu"/>-->
</localpath>
<rsync><!-- rsync的选项 -->
<commonParams params="-az"/>
<auth start="true" users="rsync_backup" passwordfile="/etc/rsync.pass"/><!-- rsync配置创建的虚拟用户和rsync客户端的密码文件 -->
<userDefinedPort start="false" port="874"/><!-- port=874 -->
<timeout start="false" time="100"/><!-- timeout=100 -->
<ssh start="false"/>
</rsync>
<!-- 每60分钟执行一次同步 -->
<failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/><!--default every 60mins execute once-->
<crontab start="false" schedule="600"><!--600mins-->
<crontabfilter start="false">
<exclude expression="*.php"></exclude>
<exclude expression="info/*"></exclude>
</crontabfilter>
</crontab>
<plugin start="false" name="command"/>
</sersync>
<plugin name="command">
<param prefix="/bin/sh" suffix="" ignoreError="true"/> <!--prefix /opt/tongbu/mmm.sh suffix-->
<filter start="false">
<include expression="(.*)\.php"/>
<include expression="(.*)\.sh"/>
</filter>
</plugin>
<plugin name="socket">
<localpath watch="/opt/tongbu">
<deshost ip="192.168.138.20" port="8009"/>
</localpath>
</plugin>
<plugin name="refreshCDN">
<localpath watch="/data0/htdocs/cms.xoyo.com/site/">
<cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>
<sendurl base="http://pic.xoyo.com/cms"/>
<regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>
</localpath>
</plugin>
</head>
注意:需要修改以后的所有地方,这边都有备注,你可以自行根据需求进行修改。
具体配置原理可以参考下图:
3)启动sersync的守护进程
#查看帮助说明
[root@nfs /usr/local/sersync]# ./sersync2 -h
set the system param
execute:echo 50000000 > /proc/sys/fs/inotify/max_user_watches
execute:echo 327679 > /proc/sys/fs/inotify/max_queued_events
parse the command param
_______________________________________________________
参数-d:启用守护进程模式
参数-r:在监控前,将监控目录与远程主机用rsync命令推送一遍
c参数-n: 指定开启守护线程的数量,默认为10个
参数-o:指定配置文件,默认使用confxml.xml文件
参数-m:单独启用其他模块,使用 -m refreshCDN 开启刷新CDN模块
参数-m:单独启用其他模块,使用 -m socket 开启socket模块
参数-m:单独启用其他模块,使用 -m http 开启http模块
不加-m参数,则默认执行同步程序
________________________________________________________
#启动sersync守护进程
[root@nfs /usr/local/sersync]# ./sersync2 -dro confxml.xml
4)测试
测试前目录查看结果如下:
在/data目录下创建一个文件,测试同步结果如下:
说明:使用sersync是可以解决之前的缺陷问题,但是这个服务自生也是存在缺陷问题,例如:不能同时监控多个目录,该服务实现多目录监控只能将之前的配置文件重新复制一份重命名,之后与之前启动守护进程一样,在重新启动一个新的进程,这样就比较麻烦。这个问题在lsyncd这个服务中就很好地解决了这个问题,这里就不在配置了sersync服务监控多目录了。
六.lsyncd简介与简单实战
1.lsyncd简介
Lysncd 实际上是lua语言封装了 inotify 和 rsync 工具,采用了 Linux 内核(2.6.13 及以后)里的 inotify 触发机制,然后通过rsync去差异同步,达到实时的效果。我认为它最令人称道的特性是,完美解决了 inotify + rsync海量文件同步带来的文件频繁发送文件列表的问题 —— 通过时间延迟或累计触发事件次数实现。另外,它的配置方式很简单,lua本身就是一种配置语言,可读性非常强。lsyncd也有多种工作模式可以选择,本地目录cp,本地目录rsync,远程目录rsyncssh。
官方开源地址:https://github.com/axkibe/lsyncd
官方配置手册:https://axkibe.github.io/lsyncd/
2.部署lsyncd
1)安装lsyncd
[root@nfs ~]# yum -y install lsyncd
2)配置lsyncd同步配置
#这里在上面的基础上在主机名为nfs新建一个目录/data1,对应在backup新建一个/backup1目录,lsyncd.conf的配置文件如下:
[root@nfs ~]# vim /etc/lsyncd.conf
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
inotifyMode = "CloseWrite",
maxProcesses = 8,
}
sync {
default.rsync,
source = "/data",
target = "rsync_backup@172.16.1.41::backup",
delete = true,
delay = 1,
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = true,
verbose = true,
password_file = "/etc/rsync.pass",
_extra = {"--bwlimit=200"}
}
}
sync {
default.rsync,
source = "/data1",
target = "rsync_backup@172.16.1.41::backup1",
delete = true,
exclude = { ".*" },
delay = 1,
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = true,
verbose = true,
password_file = "/etc/rsync.pass",
_extra = {"--bwlimit=200"}
}
}
lsync.conf配置文件详解
settings
里面是全局设置,`--`开头表示注释,下面是几个常用选项说明:
* `logfile` 定义日志文件
* `stausFile` 定义状态文件
* `nodaemon=true` 表示不启用守护模式,默认
* `statusInterval` 将lsyncd的状态写入上面的statusFile的间隔,默认10秒
* `inotifyMode` 指定inotify监控的事件,默认是`CloseWrite`,还可以是`Modify`或`CloseWrite or Modify`
* `maxProcesses` 同步进程的最大个数。假如同时有20个文件需要同步,而`maxProcesses = 8`,则最大能看到有8个rysnc进程
* `maxDelays` 累计到多少所监控的事件激活一次同步,即使后面的`delay`延迟时间还未到
sync
里面是定义同步参数,可以继续使用`maxDelays`来重写settings的全局变量。一般第一个参数指定`lsyncd`以什么模式运行:`rsync`、`rsyncssh`、`direct`三种模式:
* `default.rsync` :本地目录间同步,使用rsync,也可以达到使用ssh形式的远程rsync效果,或daemon方式连接远程rsyncd进程;
`default.direct` :本地目录间同步,使用`cp`、`rm`等命令完成差异文件备份;
`default.rsyncssh` :同步到远程主机目录,rsync的ssh模式,需要使用key来认证
* `source` 同步的源目录,使用绝对路径。
* `target` 定义目的地址.对应不同的模式有几种写法:
`/data` :本地目录同步,可用于`direct`和`rsync`模式
`172.16.1.41:/backup` :同步到远程服务器目录,可用于`rsync`和`rsyncssh`模式,拼接的命令类似于`/usr/bin/rsync -ltsd --delete --include-from=- --exclude=* SOURCE TARGET`,剩下的就是rsync的内容了,比如指定username,免密码同步
`172.16.1.41::module` :同步到远程服务器目录,用于`rsync`模式
三种模式的示例会在后面给出。
* `init` 这是一个优化选项,当`init = false`,只同步进程启动以后发生改动事件的文件,原有的目录即使有差异也不会同步。默认是`true`
* `delay` 累计事件,等待rsync同步延时时间,默认15秒(最大累计到1000个不可合并的事件)。也就是15s内监控目录下发生的改动,会累积到一次rsync同步,避免过于频繁的同步。(可合并的意思是,15s内两次修改了同一文件,最后只同步最新的文件)
* `excludeFrom` 排除选项,后面指定排除的列表文件,如`excludeFrom = "/etc/lsyncd.exclude"`,如果是简单的排除,可以使用`exclude = LIST`。
这里的排除规则写法与原生rsync有点不同,更为简单:
* 监控路径里的任何部分匹配到一个文本,都会被排除,例如`/bin/foo/bar`可以匹配规则`foo`
* 如果规则以斜线`/`开头,则从头开始要匹配全部
* 如果规则以`/`结尾,则要匹配监控路径的末尾
* `?`匹配任何字符,但不包括`/`
* `*`匹配0或多个字符,但不包括`/`
* `**`匹配0或多个字符,可以是`/`
* `delete` 为了保持target与souce完全同步,Lsyncd默认会`delete = true`来允许同步删除。它除了`false`,还有`startup`、`running`值,请参考 [Lsyncd 2.1.x ‖ Layer 4 Config ‖ Default Behavior](https://github.com/axkibe/lsyncd/wiki/Lsyncd%202.1.x%20%E2%80%96%20Layer%204%20Config%20%E2%80%96%20Default%20Behavior)。
rsync
(提示一下,`delete`和`exclude`本来都是rsync的选项,上面是配置在sync中的,我想这样做的原因是为了减少rsync的开销)
* `bwlimit` 限速,单位kb/s,与rsync相同(这么重要的选项在文档里竟然没有标出)
* `compress` 压缩传输默认为`true`。在带宽与cpu负载之间权衡,本地目录同步可以考虑把它设为`false`
* `perms` 默认保留文件权限。
* 其它rsync的选项
其它还有rsyncssh模式独有的配置项,如`host`、`targetdir`、`rsync_path`、`password_file`,见后文示例。`rsyncOps={"-avz","--delete"}`这样的写法在2.1.*版本已经不支持。
`lsyncd.conf`可以有多个`sync`,各自的source,各自的target,各自的模式,互不影响。
3)启动lsyncd
[root@nfs ~]# systemctl start lsyncd
4)测试
这里在/data目录下创建一个2.txt,在/data1目录下创建一个1.txt,之后分别看一下backup主机同步的二目录下是否存在该目录,注意:新加模块需要重启rsync这个服务。
测试结果如图:
其他模式你可以参考官方配置进行测试,这里不再过多说明。