rsync+sersync单向文件实时同步配置详解

一、为什么要用rsync+sersync架构?

1、sersync是基于inotify开发的,类似于inotify-tools的工具

2、sersync可以记录下被监听目录中发生变化的(包括增加、删除、修改)具体某一个文件或者某一个目录的名字,然后使用rsync同步的时候,只同步发生变化的文件或者目录

 

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

1、rsync+inotify-tools

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

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

 

2、rsync+sersync

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

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

 

总结:

当同步的目录数据量不大时,建议使用rsync+inotify

当同步的目录数据量很大时(几百G甚至1T以上)文件很多时,建议使用rsync+sersync

 

三、rsync+sersync配置

1、适用场景

rsync+sersync适用于目录实时同步,它是单向的,如果主服务器的文件被修改,则sersync会调用rsync命令将修改的文件(不是整个目录)同步至备服务器上。反之,备服务器上的文件修改不会被同步至主服务器,甚至还有可能被删除,具体后面会讲到。

2、环境说明

主机IP地址 部署服务 备注
192.168.100.100 sersync+rsync 主服务器,监听目录变化并执行rsync同步
192.168.100.101 rsyncd 备服务器,部署rsync server接收文件

主服务器负责监听目录变化,调用rsync进行文件同步

备服务器负责响应rsync同步请求

所有文件及目录变更操作都在主服务器(192.168.100.100)进行,备服务器接收文件同步(如果有多台备服务器部署配置完全一致)

3、环境部署

3.1 首先在备服务器配置rsync server

3.1.1 关闭selinux

$ vim /etc/selinux/config

SELINUX=disabled

3.1.2 关闭iptables

service iptables stop

3.1.3 安装rsync

$ yum -y install rsync

3.1.4 修改/etc/rsyncd.conf配置文件

$ vim /etc/rsyncd.conf

# /etc/rsyncd: configuration file for rsync daemon mode

# See rsyncd.conf man page for more options.

# configuration example:

uid = nobody    # 运行rsync进程的用户
gid = nobody   # 运行rsync进程的用户组
port = 873    # 监听端口
use chroot = no    # 默认为true,修改为no,增加对目录文件软连接的备份
read only = no    # 是否为只读
list = no    # 是否显示rsync服务端资源列表
max connections = 200    # 最大连接数
timeout = 600    # 超时时间
exclude = lost+found/    # 排除目录
transfer logging = yes    # 是否记录传输文件信息
ignore nonreadable = yes    # 是否忽略不可读文件
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2    # 不使用压缩的文件
# log file = no    # 关闭日志,这里注释掉了
log file = /var/log/rsyncd.log    # 日志文件路径
pid file = /var/run/rsyncd.pid     # PID文件路径
lock file = /var/run/rsync.lock     # 锁文件路径
secrets file = /etc/rsync.pass     # 用户认证文件
motd file = /etc/rsyncd.Motd    # 欢迎界面信息
auth users = nobody    # 认证用户
hosts allow = 192.168.100.100    # 允许主机

[wwwroot]    # 模块名
path = /data/wwwroot/    # 模块路径
comment = wwwroot    # 注释

3.1.5 创建用户认证文件

$ vim /etc/rsync.pass

nobody:mypass    # 用户名:密码,每行一个

$ chmod 600 /etc/rsync.pass

3.1.6 启动rsyncd服务

service rsyncd start

chkconfig rsyncd on

3.2 主服务器配置rsync+sersync

3.2.1 关闭selinux

$ vim /etc/selinux/config

SELINUX=disabled

3.2.2 关闭iptables

service iptables stop

3.2.3 安装rsync

$ yum -y install rsync

3.2.4 安装sersync

$ cd /usr/local/src

$ wget http://sersync.googlecode.com/files/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

3.2.5 创建rsync认证密码文件

$ echo “mypass” > /etc/rsync.password

$ chmod 600 /etc/rsync.password

将在备服务器/etc/rsync.pass中配置的密码写入主服务器的rsync密码认证文件/etc/rsync.password中,并赋予600权限

3.2.6 rsync连接测试

$ rsync -artuz –port=873 –progress /data/wwwroot/  nobody@192.168.100.101::wwwroot –password-file=/etc/rsync.password

3.2.7 修改sersync配置文件/usr/local/sersync/confxml.xml

$ vim /usr/local/sersync/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=”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=”/data/wwwroot“>
<remote ip=”192.168.100.101” name=”wwwroot“/>
<!–<remote ip=”192.168.8.39″ name=”tongbu”/>–>
<!–<remote ip=”192.168.8.40″ name=”tongbu”/>–>
</localpath>
<rsync>
<commonParams params=”-artuz”/>
<auth start=”true” users=”nobody” passwordfile=”/etc/rsync.password“/>
<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=”true” 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>

红字部分为必须修改参数,其余参数可根据实际情况修改,以下是重要参数说明:

<debug start=”false”/>    # 是否开启debug模式,用户调试及日志输出

<filter start=”false”>    # 是否启用文件过滤,类似rsync –exclude,下面exclude为过滤文件列表,每行一个
<exclude expression=”(.*)\.svn”></exclude>
<exclude expression=”(.*)\.gz”></exclude>
<exclude expression=”^info/*”></exclude>
<exclude expression=”^static/*”></exclude>
</filter>

<inotify>    # 监听目录变化的事件类型,true为监听,false为不监听
<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>    # sersync同步配置
<localpath watch=”/data/wwwroot“>    # 监听目录
<remote ip=”192.168.100.101” name=”wwwroot“/>    # rsync server的IP以及模块
</localpath>
<rsync>
<commonParams params=”-artuz”/>    # rsync命令参数
<auth start=”true” users=”nobody” passwordfile=”/etc/rsync.password“/>    # 开启用户认证,配置用户名及认证密码文件
<userDefinedPort start=”false” port=”874″/><!– port=874 –>    # 用户自定义端口(–port参数)
<timeout start=”false” time=”100″/><!– timeout=100 –>    # rsync同步超时时间(–timeout参数)
<ssh start=”false”/>    # 是否使用ssh进行传输(加密传输)
</rsync>
<failLog path=”/tmp/rsync_fail_log.sh” timeToExecute=”60″/>    # rsync同步失败后记录的日志文件,以及多久重试一次(单位:分钟),后文详细说明
<crontab start=”true” schedule=”600“>    # sersync的计划任务,负责执行完整同步,保证两端文件一致,以及多久重试一次(单位:分钟),后文详细说明
<crontabfilter start=”false”>    # 是否启用计划任务文件过滤,类似rsync –exclude,下面exclude为过滤文件列表,每行一个
<exclude expression=”*.php”></exclude>
<exclude expression=”info/*”></exclude>
</crontabfilter>
</crontab>
<plugin start=”false” name=”command”/>    # 是否使用其他插件
</sersync>

3.2.8 启动sersync

$ /usr/local/sersync/sersync2 -d -r -n 20 -o /usr/local/sersync/confxml.xml

命令参数说明:

-d : 启用守护进程模式

-r : 启动前进行一次目录完整同步,保证两段文件一致。注意这里会使用rsync –delete参数,如果文件只存在在备服务器,则备服务器上该文件会被删除(因为主服务器没有这个文件)

-n : 指定开启守护线程的数量,默认为10个,注意rsync server的max connections数量要大于线程数量的两倍加2,计算公式max connections > thread num * 2 + 2

-o : 指定配置文件,默认使用confxml.xml文件

控制台输出信息说明:

set the system param
execute:echo 50000000 > /proc/sys/fs/inotify/max_user_watches    # 修改inotify内核参数max_user_watches,后文有内核参数说明
execute:echo 327679 > /proc/sys/fs/inotify/max_queued_events    # 修改inotify内核参数max_queued_events,后文有内核参数说明
parse the command param    # 获取命令行参数
option: -d run as a daemon
option: -r rsync all the local files to the remote servers before the sersync work
option: -n thread num is: 20
option: -o config xml name: /usr/local/sersync/confxml.xml
parse xml config file    # 解析配置文件
host ip : localhost host port: 8008
daemon start,sersync run behind the console
Start the crontab Every 600 minutes rsync all the files to the remote servers entirely    # 开启计划任务,每600分钟进行完整同步
use rsync password-file :    # 读取rsync客户端配置
user is nobody    # rsync用户名
passwordfile is /etc/rsync.password    # rsync密码认证文件
config xml parse success
please set /etc/rsyncd.conf max connections=0 Manually
sersync working thread 22 = 1(primary thread) + 1(fail retry thread) + 20(daemon sub threads)    # sersync工作线程数(1个主线程+1个错误重试线程+20个rsync同步线程)
Max threads numbers is: 42 = 22(Thread pool nums) + 20(Sub threads)    # 最大线程数,最大线程数量要小于rsync server的max connections数量
please according your cpu ,use -n param to adjust the cpu rate
——————————————
rsync the directory recursivly to the remote servers once
working please wait…
execute command: cd /data/wwwroot && rsync -artu -R –delete ./ nobody@192.168.100.101::wwwroot –password-file=/etc/rsync.password >/dev/null 2>&1    # -r参数默认在开启前执行rsync完整同步
run the sersync:
watch path is: /data/wwwroot    # sersync开始监听目录变化

如果需要开机自启动,添加到/etc/rc.local中

$ echo “/usr/local/sersync/sersync2 -d -r -n 20 -o /usr/local/sersync/confxml.xml” >> /etc/rc.local

3.3 需要注意的内容

3.3.1 max connections

备服务器/etc/rsyncd.conf配置中的max connections数量必须大于两倍加2的sersync线程数量,否则会出现rsync队列堵塞的情况

计算公式max connections > thread num * 2 + 2

3.3.2 sersync2命令参数

sersync2命令的-r参数请谨慎使用,该参数会导致只在备服务器上的文件被删除,因为使用了rsync –delete参数

3.3.3 sersync failLog错误重试

sersync的failLog错误重试机制能大大保证两端的文件是一致的,假设一个文件执行rsync同步失败,sersync会将这个文件记录到failLog中,之后根据timeToExecute设定的时间(这里是60分钟),每隔60分钟执行一次,如果执行还是失败,还有sersync crontab完整rsync同步来保证文件一致。

但这里需要注意的是,failLog这个文件会不断增长,在执行重试后并不会清空该文件内容,如果错误比较多也会导致整体性能问题,这里给出一个建议,用系统的crontab来执行这个错误重试,参考脚本如下:

$ vi /usr/local/sersync/fail_retry.sh

#!/bin/bash
tmpfile=$(mktemp -u /tmp/rsync_fail_log_XXXX.sh)
mv /tmp/rsync_fail_log.sh $tmpfile
touch /tmp/rsync_fail_log.sh
chmod 777 /tmp/rsync_fail_log.sh
bash $tmpfile
rm -f $tmpfile

然后将脚本配置crontab来执行,这里是每半小时执行一次

$ chmod +x /usr/local/sersync/fail_retry.sh

$ crontab -e

*/30 * * * * /bin/bash /usr/local/sersync/fail_retry.sh

$ systemctl reload crond

3.3.4 sersync crontab完整同步

与sersync2命令参数-r一样,该计划任务也会使用rsync –delete参数,请谨慎使用

也可以使用系统的crontab来进行rsync完整同步

3.3.5 关于日志输出

备服务器/etc/rsyncd.conf里通过log file指定日志文件路径,transfer logging决定是否记录传输文件

sersync记录详细日志需要开启debug模式,<debug start=”true”/>

并且使用/usr/local/sersync/sersync2 -d -r -n 20 -o /usr/local/sersync/confxml.xml &>> /var/log/sersync.log将输出内容追加至文件

3.3.6 内核参数说明及调整

内核参数中有三个参数用于调整inotify属性:

/proc/sys/fs/inotify/max_queued_events    # 默认值: 16384 该文件中的值为调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,超出这个值得事件被丢弃,但会触发IN_Q_OVERFLOW事件
/proc/sys/fs/inotify/max_user_instances    # 默认值: 128 指定了每一个real user ID可创建的inotify instatnces的数量上限
/proc/sys/fs/inotify/max_user_watches    # 默认值: 8192 指定了每个inotify instance相关联的watches的上限

注意: max_queued_events 是 inotify 管理的队列的最大长度,文件系统变化越频繁,这个值就应该越大

在启动sersync后,sersync默认修改两个内核参数

execute:echo 50000000 > /proc/sys/fs/inotify/max_user_watches
execute:echo 327679 > /proc/sys/fs/inotify/max_queued_events

所以在启动sersync前做的任何参数调整都会被覆盖(无法通过config.xml修改)

如果监听的目录数量不是非常多(小于50000000),文件变更也不是特别频繁,则可以忽略以下步骤,了解启动sersync会默认修改内核参数即可

解决办法是在启动sersync后再设置一遍内核参数(如果需要自行调整参数值),将其覆盖

可以事先将参数配置写入/etc/sysctl.conf

$ echo “fs.inotify.max_queued_events = 999999999” >> /etc/sysctl.conf

$ echo “fs.inotify.max_user_watches = 999999999” >> /etc/sysctl.conf

$ echo “fs.inotify.max_user_instances = 65535” >> /etc/sysctl.conf

然后在每次启动sersync后执行一次sysctl -p,不要忘了加到/etc/rc.local中,需要保证sysctl命令在sersync之后

$ sysctl -p

$ echo “sysctl -p” >> /etc/rc.local

$ vi /etc/rc.local

/usr/local/sersync/sersync2 -d -r -n 20 -o /usr/local/sersync/confxml.xml
sysctl -p

扩展内容:使用supervisor管理sersync进程

安装supervisor,需要安装epel源

$ yum -y install supervisor

配置supervisor

$  vim /etc/supervisord.d/sersync2.ini

[program:sersync2]    # 项目名
command=/usr/local/sersync/sersync2 -r -n 20 -o /usr/local/sersync/confxml.xml    # 执行命令,supervisor管理进程需要是前台进程,所以不能使用-d参数
stdout_logfile=/var/logs/sersync2.log    # 标准输出日志文件路径
stdout_logfile_maxbytes=100MB    # 单个日志文件大小
stdout_logfile_backups=10    # 日志文件切割次数
stderr_logfile=/var/logs/sersync2.error.log    # 标准错误输出日志文件路径
stderr_logfile_maxbytes=100MB    # 单个日志文件大小
stderr_logfile_backups=10    # 日志文件切割次数

启动supervisor,并配置开机自启动

$ service supervisord start

$ chkconfig supervisord on

转载请注明出处:http://www.madown.com/2017/05/10/rsyncsersync单向文件实时同步配置详解

发表评论

电子邮件地址不会被公开。 必填项已用*标注