inotify 高效改进版 sersync 结合 rsync 实现数据实时增量同步

本文最后更新于:2021年12月31日 下午

sersync类似于inotify,同样用于监控,但它克服了inotify的几个缺点。本文记录sersync相关内容。

简介

sersync主要用于服务器同步,web镜像等功能。基于boost1.43.0,inotify api,rsync command.开发。

鉴于 inotify 存在一定问题,后开发的工具 sersync 克服了inotify的几个缺点。

  • inotify最大的不足是会产生重复事件,或者同一个目录下多个文件的操作会产生多个事件(例如,当监控目录中有5个文件时,删除目录时会产生6个监控事件),从而导致重复调用rsync命令。而且vim文件时,inotify会监控到临时文件的事件,但这些事件相对于rsync来说是不应该被监控的。

  • 项目地址:https://code.google.com/archive/p/sersync/

    此网站中有下载、安装、使用等等详细的中文介绍。

  • 下载地址:https://code.google.com/archive/p/sersync/downloads

优点

  1. sersync是使用c++编写,而且对linux系统文件系统产生的临时文件和重复的文件操作进行过滤,所以在结合rsync同步的时候,节省了运行时耗和网络资源。因此更快。

  2. sersync配置很简单,其中bin目录下已经有静态编译好的2进制文件,配合bin目录下的xml配置文件直接使用即可。

  3. sersync使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器实时保持同步状态。

  4. sersync有出错处理机制,通过失败队列对出错的文件重新同步,如果仍旧失败,则按设定时长对同步失败的文件重新同步。

  5. sersync自带crontab功能,只需在xml配置文件中开启,即可按要求隔一段时间整体同步一次。无需再额外配置crontab功能。

  6. sersync可以二次开发。

rsync+inotify-tools 与 rsync+sersync 架构的区别

rsync+inotify-tools

  1. inotify只能记录下被监听的目录发生了变化(增,删,改)并没有把具体是哪个文件或者哪个目录发生了变化记录下来;

  2. rsync在同步的时候,并不知道具体是哪个文件或目录发生了变化,每次都是对整个目录进行同步,当数据量很大时,整个目录同步非常耗时(rsync要对整个目录遍历查找对比文件),因此效率很低

rsync+sersync

  1. sersync可以记录被监听目录中发生变化的(增,删,改)具体某个文件或目录的名字;

  2. rsync在同步时,只同步发生变化的文件或目录(每次发生变化的数据相对整个同步目录数据来说很小,rsync在遍历查找对比文件时,速度很快),因此效率很高。

下载安装

  • sersync工具包无需任何安装,解压即可使用。
1
2
3
4
5
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz
tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz
cp -a GNU-Linux-x86 /usr/local/sersync
echo "PATH=$PATH:/usr/local/sersync" > /etc/profile.d/sersync.sh
source /etc/profile.d/sersync.sh
  • sersync目录/usr/local/sersync只有两个文件:一个是二进制程序文件,一个是xml格式的配置文件。
1
2
$ ls /usr/local/sersync/
confxml.xml sersync2

使用步骤

rsync部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
1、关闭SELINUX(sersync_rsync_client、rsync_server均配置)
vi /etc/selinux/config
修改下面一行代码:
SELINUX=disabled
运行此命令立即生效。
setenforce 0


2、开启防火墙tcp 873端口、或关掉防火墙(sersync_rsync_client、rsync_server均配置)
vi /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 873 -j ACCEPT
或者关闭防火墙
service iptables stop
chkconfig iptables off


3、安装rsync服务端软件(sersync_rsync_client配置)
yum install rsync


4、安装xinetd(rsync_server配置)
yum install rsync xinetd
vi /etc/xinetd.d/rsync
修改disable的值为no:
disable = no

启动xinetd(CentOS中是以xinetd来管理Rsync服务的)
/etc/init.d/xinetd start
chkconfig xinetd on
rsync --daemon --config=/etc/rsyncd.conf
echo "rsync --daemon --config=/etc/rsyncd.conf" >> /etc/rc.local


5、创建rsyncd.conf配置文件(rsync_server配置。假如需要同步多个目录,注意加多个目录;此root是rsync的认证账号,后面步骤会配置认证账号和密码)
创建配置文件:
vi /etc/rsyncd.conf
log file = /var/log/rsyncd.log
pidfile = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
secrets file = /etc/rsyncd.secret
motd file = /etc/rsyncd.motd
[test]
path = /home/xyz/
comment = test
uid = root
gid = root
incoming chmod = Du=rwx,Dog=rx,Fu=rwx,Fgo=rx
port=873
use chroot = no
read only = no
list = no
max connections = 200
timeout = 600
auth users = root
hosts allow = 192.168.1.103
hosts deny = *
目录权限(如果uid和gid都是root,这里不用操作):
cd /home
chown -hR root.root xyz/ #如果xyz目录是在root下新建的,默认就是root权限。


6.创建用户认证文件(rsync_server)
配置文件
vi /etc/rsyncd.passwd
root:123456
保存退出


7.设置文件权限(rsync_server)
设置文件所有者读取、写入权限
chmod 600 /etc/rsyncd.conf
chmod 600 /etc/rsyncd.passwd


8.启动rsync(rsync_server)
/etc/init.d/xinetd start
参考指令
停止:service xinetd stop
启动:service xinetd restart


9、创建用户认证文件(sersync_rsync_client配置)
配置文件
vi /etc/rsyncd.passwd
123456
保存退出
chmod 600 /etc/rsyncd.passwd


10、从sersync_rsync_client手动rsync同步到rsync_server看下,只有成功后(查看日志),下面sersync才会成功。(sersync_rsync_client上运行此命令测试)
rsync -avzrtopgL --progress /root/ root@192.168.1.189::test/ --password-file=/etc/rsyncd.passwd

sersync部署(sersync_rsync_client配置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
1、查看服务器内核是否支持inotify
列出文件目录
ll /proc/sys/fs/inotify
出现下面的内容、说明服务器内核支持inotify
-rw-r--r-- 1 root root 0 Dec 25 12:03 max_queued_events
-rw-r--r-- 1 root root 0 Dec 25 15:05 max_user_instances
-rw-r--r-- 1 root root 0 Dec 25 12:03 max_user_watches
备注:centos6.9默认支持inotify


2.修改inotify默认参数(inotify默认内核参数值太小)
sysctl -a | grep max_queued_events
sysctl -a | grep max_user_watches
sysctl -a | grep max_user_instances
修改参数
sysctl -w fs.inotify.max_queued_events="99999999"
sysctl -w fs.inotify.max_user_watches="99999999"
sysctl -w fs.inotify.max_user_instances="65535"
生效
sysctl -p
参数说明:
max_queued_events:
inotify队列最大长度,如果值太小,会出现” Event Queue Overflow “错误,导致监控文件不准确
max_user_watches:
要同步的文件包含多少目录,可以用:find /var/www/synctest -type d | wc -l 统计,必须保证max_user_watches值大于统计结果(这里/var/www/synctest为同步文件目录)
max_user_instances:
每个用户创建inotify实例最大值


3、最好更改最大连接数、最大文件描述符。
vi /etc/pam.d/login
session required /lib64/security/pam_limits.so
vi /etc/security/limits.conf
* soft nproc 65535
* hard nproc 65535
* soft nofile 65535
* hard nofile 65535
重启服务器


4、安装sersync
cd /usr/local/src
wget https://sersync.googlecode.com/files/sersync2.5.4_64bit_binary_stable_final.tar.gz
如果下载不了,用github这个
wget --no-check-certificate https://raw.githubusercontent.com/orangle/sersync/master/release/sersync2.5.4_64bit_binary_stable_final.tar.gz
tar zxvf sersync2.5.4_64bit_binary_stable_final.tar.gz
mv GNU-Linux-x86 /usr/local/sersync
cd /usr/local/sersync


5、配置sersync
cp confxml.xml confxml.xml-bak
vi confxml.xml
设置如下代码:(如果需要同步多目录,就再建一个如confxmldata.xml,port端口8008不能冲突(测试好像不改也没关系),改成其他端口。localpath watch 改下,failLog path这个脚本文件也改下,每个xml文件中只保留自己的localpath watch )
<?xml version="1.0" encoding="ISO-8859-1"?>
<head version="2.5">
<host hostip="localhost" port="8008"></host>
<debug start="false"/>
<fileSystem xfs="false"/>
<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="false"/>
<closeWrite start="true"/>
<moveFrom start="true"/>
<moveTo start="true"/>
<attrib start="false"/>
<modify start="false"/>
</inotify>
<sersync>
<localpath watch="/home/xyz">
<remote ip="192.168.1.189" name="test"/>
</localpath>
<rsync>
<commonParams params="-artuz"/>
<auth start="true" users="root" passwordfile="/etc/rsyncd.passwd"/>
<userDefinedPort start="false" port="874"/><!-- port=874 -->
<timeout start="false" time="100"/><!-- timeout=100 -->
<ssh start="false"/>
</rsync>
<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>
参数说明:
如果A服务器新建、删除目录都会触发同步到B服务器。但是A服务器删除文件,不会触发到B服务器。
localpath watch=”/home/xyz“
name=”test”: #目标服务器rsync同步目录模块名称
users=”root”: #目标服务器rsync同步用户名
passwordfile=”/etc/rsyncd.passwd”: #目标服务器rsync同步用户的密码在源服务器的存放路径
remote ip=”192.168.1.189”: #对端服务器ip
failLog path=”/tmp/rsync_fail_log.sh” #脚本运行失败日志记录
start=”true” #设置为true,每隔600分钟执行一次全盘同步
delete start #只做增量备份,可以吧这个设置为flase。但是如果两边要一样就设置为true
<!-- :另外注释不用用#号,要注意


6、先执行下同步。
/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml



7、设置sersync监控开机自动执行(如果同步多个目录,下面还需要加一条)
vi /etc/rc.d/rc.local
/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml (开机自启动,建议不要-r,只有第一次才需要加-r)
-o指定配置文件
-d在后台启动
-r在一个开始两台服务器不一致,先做一次同步,任何再有新数据就同步了



8、添加脚本监控sersync是否正常运行(如果需要同步多个目录,另外一个就用crontab做个定时执行上面那个命令,因为我没试过用下面这个脚本来检测两个文件,怕有bug)
vi /home/crontab/check_sersync.sh (没有目录先新建下)
#!/bin/sh
sersync="/usr/local/sersync/sersync2"
confxml="/usr/local/sersync/confxml.xml"
status=$(ps aux |grep 'sersync2'|grep -v 'grep'|wc -l)
if [ $status -eq 0 ];
then
$sersync -d -r -o $confxml &
else
exit 0;
fi

添加脚本执行权限
chmod +x /home/crontab/check_sersync.sh

做定时任务:
vi /etc/crontab
*/5 * * * * root /home/crontab/check_sersync.sh > /dev/null 2>&1

重新加载服务
/etc/init.d/crond restart

备注

1
2
3
4
5
6
7
1、日志在/var/log/rsyncd.log文件

2、验证触发同步命令
cd /usr/local/sersync/
./sersync2 -d -r
或者
/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml (-o应该是接文件)

参考资料