通过inotify+rsync | 实现数据实时同步与备份
👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
虽然小架构已实现但是NFS服务器存在一个冗余性问题,倘若崩溃那么存放于服务器的wordpress资源就有可能出现丢失情况,针对这一情况应准备backup服务器通过inotify和rsysnc技术的集合实现数据的实时同步最大限度的保证数据的原有性。
架构图:
实现思路:
通过inotify功能监控NFS服务器存放wordpress资源的目录当events发生,在events发生的同时启动rsync客户端将被监控的目录拷贝到rsync服务器的共享目录当中。
1)共享目录:存在于服务器,当rsync以独立服务运行时用于rsync客户端push或pull文件。
2)(由于rsync特性只拷贝的是增量的内容,因此只会将触发event的变化拷贝到rsync服务器的共享文件中)
第一步:实现inotify监控NFS服务器存放wordpress资源目录的evebts发生。
inotify核心参数:
max_queued_events:inotify 事件队列最大长度,如值太小会出现 Event Queue Overflow 错误,默认值:16384, 生产环境建议调大,比如:327679(inotify监控文件系统,每发生一个事件都会记录到队列当中,此选项就是控制事件队列的数量)
max_user_instances:每个用户创建inotify实例最大值,默认值:128 (用户能够创建notify的数量,默认128个也就是能够监控文件系统中128个目录<正常够用>)
max_user_watches:可以监视的文件的总数量(inotifywait 单进程),默认值:8192,建议调大(一个inotify所能监控的目录下面的文件数量<默认值太小>)
查看命令:
cat /proc/sys/fs/inotify/max_queued_events
cat /proc/sys/fs/inotify/max_user_instances
cat /proc/sys/fs/inotify/max_user_watches|
cat /proc/sys/fs/inotify/* #能够同时查看以上三个参数的值
1.调整inotify核心参数:
vim /etc/sysctl.conf
fs.inotify.max_queued_events = 100000
fs.inotify.max_user_watches = 1000000
sysctl -p #识别修改的inotify值
<识别成功>
2.安装inotify-tools工具配合inotify功能对文件进行监控。
yum -y install inotify-tools
inotify-tools包主要工具:
inotifywait: 在被监控的文件或目录上等待特定文件系统事件(open ,close,delete等)发生,常用于实时同步的目录监控。
inotifywatch:收集被监控的文件系统使用的统计数据,指文件系统事件发生的次数统计
inotifywait选项:
time格式选项:自定义时间格式
format选项:定义出现events的格式
%T #输出时间格式中定义的时间格式信息,通过 --timefmt option 语法格式指定时间信息
%w #事件出现时,监控文件或目录的名称信息,相当于dirname
%f #事件出现时,将显示监控目录下触发事件的文件或目录信息,否则为空,相当于basename
%e #显示发生的事件信息,不同的事件默认用逗号分隔
%Xe #显示发生的事件信息,不同的事件指定用X进行分隔
inotifywait -e 选项指定的事件类型:
create #文件或目录创建
delete #文件或目录被删除
modify #文件或目录内容被写入
attrib #文件或目录属性改变
close_write #文件或目录关闭,在写入模式打开之后关闭的
close_nowrite #文件或目录关闭,在只读模式打开之后关闭的
close #文件或目录关闭,不管读或是写模式
open #文件或目录被打开
lsdir #浏览目录内容
moved_to #文件或目录被移动到监控的目录中
moved_from #文件或目录从监控的目录中被移动
move #文件或目录不管移动到或是移出监控目录都触发事件
access #文件或目录内容被读取
delete_self #文件或目录被删除,目录本身被删除
unmount #取消挂载
PS:如果自定义time格式不能单独使用必须被format所引用否则报错。
3.监控NFS服务器存储wordpress资源的目录。
inotifywait -mdrq /data/wordpress --timefmt "%Y-%m-%d %H:%M:%S" --format "%T %w %f event: %:e" -e create,delete,moved_to,close_write,attrib -o /data/wp_inotify/wp.log
4.当NFS服务器存储wordpress资源的目录发生变化时,inotifywait是否能够监控此目录并将events信息输出到 /data/wp_inotify/wp.log。
tail -f /data/wp_inotify/wp.log
<成功>
第二步:搭建rsync服务器
rsync 常用于做为 linux系统下的数据镜像备份工具,实现远程同步,支持本地复制,或者与其他SSH、rsync主机同步数据,支持增量备份,配合任务计划,rsync能实现定时或间隔同步,配合inotify或sersync,可以实现触发式的实时数据同步
官方网站: http://rsync.samba.org/
软件包:rsync,rsync-daemon(CentOS 8才有)
服务文件:/usr/lib/systemd/system/rsyncd.service
配置文件:/etc/rsyncd.conf
端口:873/tcp
工作模式:
rsync有三种工作方式:
1. 本地文件系统上实现同步。命令行语法格式为上述"Local"段的格式。
2. 本地主机使用远程shell和远程主机通信。命令行语法格式为上述"Access via remote shell"段的格式。(ssh方式需要验证身份)
3. 本地主机通过网络套接字连接远程主机上的rsync daemon。命令行语法格式为上述"Access via rsync daemon"段的格式<rsync以独立服务运行,需搭建服务器>
常见选项:
-v:显示rsync过程中详细信息。可以使用"-vvvv"获取更详细信息。
-P:显示文件传输的进度信息。(实际上"-P"="--partial --progress",其中的"--progress"才是显
示进度信息的)。
-n --dry-run :仅测试传输,而不实际传输。常和"-vvvv"配合使用来查看rsync是如何工作的。
-a --archive :归档模式,表示递归传输并保持文件属性。等同于"-rtopgDl"。
-r --recursive:递归到目录中去。
-t --times:保持mtime属性。强烈建议任何时候都加上"-t",否则目标文件mtime会设置为系统时间,导致下次更新检查出mtime不同从而导致增量传输无效。
-o --owner:保持owner属性(属主)。
-g --group:保持group属性(属组)。
-p --perms:保持perms属性(权限,不包括特殊权限)。
-D :是"--device --specials"选项的组合,即也拷贝设备文件和特殊文件。
-l --links:如果文件是软链接文件,则拷贝软链接本身而非软链接所指向的对象
-z :传输时进行压缩提高效率
-R --relative:使用相对路径。意味着将命令行中指定的全路径而非路径最尾部的文件名发送给服务端,包括它们的属性。用法见下文示例。
--size-only :默认算法是检查文件大小和mtime不同的文件,使用此选项将只检查文件大小。
-u --update :仅在源mtime比目标已存在文件的mtime新时才拷贝。注意,该选项是接收端判断的,不会影响删除行为。
-d --dirs :以不递归的方式拷贝目录本身。默认递归时,如果源为"dir1/file1",则不会拷贝dir1目录,使用该选项将拷贝dir1但不拷贝file1。
--max-size :限制rsync传输的最大文件大小。可以使用单位后缀,还可以是一个小数值(例如:"--
max-size=1.5m")
--min-size :限制rsync传输的最小文件大小。这可以用于禁止传输小文件或那些垃圾文件。
--exclude :指定排除规则来排除不需要传输的文件。
--delete :以SRC为主,对DEST进行同步。多则删之,少则补之。注意"--delete"是在接收端执行的,所以它是在exclude/include规则生效之后才执行的。
-b --backup :对目标上已存在的文件做一个备份,备份的文件名后默认使用"~"做后缀。
--backup-dir:指定备份文件的保存路径。不指定时默认和待备份文件保存在同一目录下。
-e :指定所要使用的远程shell程序,默认为ssh。
--port :连接daemon时使用的端口号,默认为873端口。
--password-file:daemon模式时的密码文件,可以从中读取密码实现非交互式。注意,这不是远程shell认证的密码,而是rsync模块认证的密码。
-W --whole-file:rsync将不再使用增量传输,而是全量传输。在网络带宽高于磁盘带宽时,该选项比增量传输更高效。
--existing :要求只更新目标端已存在的文件,目标端还不存在的文件不传输。注意,使用相对路径时如果上层目录不存在也不会传输。
--ignore-existing:要求只更新目标端不存在的文件。和"--existing"结合使用有特殊功能,见下文示例。
--remove-source-files:要求删除源端已经成功传输的文件
命令格式:
#Access via rsync daemon:
Pull:
rsync [OPTION...] [USER@]HOST::SRC... [DEST]
rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
Push:
rsync [OPTION...] SRC... [USER@]HOST::DEST
rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
1.rsync服务器安装软件rsync rsync-daemon rsync客户机(存储wordpress资源的NFS服务器)只安装rsync。
yunm -y install rsync rsync-daemon
2.打开rsync服务器的主配置文件,创建共享文件并指定相关策略(如果是centos7没有安装rsync-daemon则没有此文件,需手动创建)。
vim /etc/rsyncd.conf
uid = root #指定哪个以用户来访问共享目录,将之指定为生成的文件所有者,默认为nobody
gid = root #默认为nobody,与NFS服务器一样存在账号压榨情况因此需要指定一个账号。
max connections = 0 #rsync客户端能够连接rsync服务器共享文件最多的连接数量,0表示关闭限制。
ignore errors #忽略掉某些错误,如:文件类型
exclude = lost+found/ #排除掉的目录种类
log file = /var/log/rsyncd.log #以下三项为日志、进程、锁的存放路径
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
reverse lookup = no #是否开启反向解析功能
#hosts allow = 10.0.0.0/24 #指定能够访问rsync服务器共享文件夹的路劲
[wp_backup] #每个模块名对应一个不同的path目录,如果同名后面模块生效
path = /data/wp_backup/ #srync服务器共享文件的路径
comment = backup dir #注释说明
read only = no #默认是yes,即只读,此功能关闭即说明客户端访问共享文件拥有w权限。
auth users = cql #默认anonymous可以访问rsync服务器,设置授权账号(此账号自定义<虚拟>),
secrets file = /etc/rsync.pas #虚拟账号密码的文件路径(需创建) 格式: user:passwd
PS:
1)客户机想要put网络共享文件资源,既要开放客户机对此文件的w权限也要开放在文件系统中的w权限(建议777)
2)用于验证rsync客户机访问服务器虚拟账号密码文件,无论服务器还是客户机都应存档一份。(客户机只存档密码主要为了避免在验证的过程中进行交互式操作)
3)用于验证rsync客户机访问服务器虚拟账号密码文件,应修该其权限(600),避免除非所有者以外的用户查看后泄露。
3.启动rsync服务,查看是否已开启873默认端口。
systemctl enable --now rsyncd #安装rsync-daemon可用
rsync --daemon #Centos7无法安装rsync-daemon使用(如果想关闭则用killall命令关闭),可加入/etc/rc.d/rc.local实现开机启动
4.rsync客户机查看rsync服务器的共享文件情况。
注:搭建的rsync服务器ip为10.0.0.40且backup dir 为共享文件中的comment备注。
#rsync服务器无账号验证查看共享目录时使用此命令
rsync rsync://rsync服务器IP
#rsync服务器需要账号验证时使用此命令查看共享目录(非交互式,客户机使用的密码文件需存在)
rsync --password-file=/etc/rsync.pas rsync://cql@10.0.0.40/wp_backup
<因服务器设置了账号验证所以采用非交互式的方式查看>
5.rsync客户端(NFS服务器),将存放wordpress资源的目录数据,同步到rsync服务器的共享文件夹<非交互式>。
rsync -az --delete --password-file=/etc/rsync.pas /data/wordpress/ rsync://cql@10.0.0.40/wp_backup
<可以看到原先在rsync服务器上并没有数据的共享文件夹经过rsync客户端的同步后数据已经变得一致>
👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆
👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
以上虽然实现了对资源发生events时的监控与资源的数据同步,却未能够做到“实时”同步效果,只有结合脚本才能达到这一目的。
第三步:在数据服务器(NFS服务器=rsync客户端)上创建inotify_rsync.sh脚本
注意: 此脚本执行前先确保两主机初始数据处于同步状态,此脚本实现后续的数据同步
1.创建并执行inotify_rsync.sh 脚本(死循环脚本)
#!/bin/bash
SRC='/data/wordpress/'
DEST='cql@10.0.0.40::wp_backup'
rpm -q rsync &> /dev/null || yum -y install rsync
inotifywait -mrq ${SRC} --exclude=".*\.swp" --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %w %f' -e create,delete,moved_to,close_write,attrib |while read DATE TIME DIR FILE;do
FILEPATH=${DIR}${FILE}
rsync -az --delete --password-file=/etc/rsync.pas $SRC $DEST && echo "At ${TIME} on ${DATE}, file $FILEPATH was backuped up via rsync" >> /var/log/changelist.log
done
PS:运行脚本后会在前台执行进程,但后台执行进程仍旧与终端存在关系(关闭终端后进程也将会结束),进程想要脱离与终端的关系则使用nuhup命令(必须要输入绝对路径,因为进程与当前终端脱离了关系,否则会无法找到此脚本开启进程、进程会自动关闭<可以去掉垃圾桶观察错误信息>)
nohup /root/inotify_rsync.sh &> /dev/null &
2。开始测试
1)登录wordpress发表文章(上传资源),监测定义的日志文件。
2)可以看到日志文件的确是按照脚本定义的格式进行输出
3)上传资源后NFS服务器存放wordpress资源目录size必然增大,而根据死循环脚本的执行逻辑会持续监控该目录倘若发生事件那么势必会通过配合rsync将出发事件的文件拷贝到远程rsync服务器的dest目录(dest目录必然是共享目录)中,对比其大小就可以得出rsync功能是否生效。
<成功!!!原本NFS服务器存放wordpress资源目录的文件size为59M(上传资源后文件为60)、而rsync服务器上的dest目录在执行脚本前通过rsync同步数据过一次(size为59),执行脚本后发表文章(上传资源)再对比双方文件数据size为一致!!!>
注意事项:拷贝脚本后如果相关参数确认正确还出现以下报错(无法打开$SRC)则可能为编码问题,通过以下命令处理脚本文件即可解决。
sed 's/\xc2\xa0/ /g' -i inotify_rsync.sh
报错信息:
Setting up watches.
Couldn't watch -mrq: No such file or directory
sersync 介绍(通过sersync替代inotify——rsync.sh脚本)
sersync类似于inotify和rsync的集合,同样用于监控,但它克服了脚本的缺点。
inotify最大的不足是会产生重复事件,或者同一个目录下多个文件的操作会产生多个事件,例如,当监控目录中有5个文件时,删除目录时会产生6个监控事件,从而导致重复调用rsync命令。另外比如:vim文件时,inotify会监控到临时文件的事件,但这些事件相对于rsync来说是不应该被监控的。
sersync下载地址: https://code.google.com/archive/p/sersync/downloads
1.解压sesync到指定目录并修改文件名。
tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz -C /usr/local/
mv /usr/local/GNU-Linux-x86 /usr/local/sersync
2.加入到PATH路径当中(sersync目录只有两个文件:一个是二进制程序文件,一个是xml格式的配置文件)
echo 'PATH=/usr/local/sersync:$PATH' > /etc/profile.d/sersync.sh
3.修改配置文件
<修改前>
<?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"> #不开启文件过滤功能,当为true时,以下类型的文件将不同
步
<exclude expression="(.*)\.svn"></exclude>
<exclude expression="(.*)\.gz"></exclude>
<exclude expression="înfo/*"></exclude>
<exclude expression="^static/*"></exclude>
</filter>
<inotify> # 监控事件,默认监控
delete/close_write/moved_from/moved_to/create folder
<delete start="true"/>
<createFolder start="true"/>
<createFile start="false"/>
<closeWrite start="true"/>
<moveFrom start="true"/>
<moveTo start="true"/>
<attrib start="true"/> #修改此行为true,文件属性变化后也会同步
<modify start="false"/>
</inotify>
<sersync> # rsync命令的配置段
<localpath watch="/data/www"> #修改此行,需要同步的源目录或文件,建议同步目
录
<remote ip="备份服务器IP" name="backup"/> #修改此行,指定备份服务器(rsync服务器)地址和rsync daemon的模块名(rsync服务器的共享文件夹),如果下面开启了ssh start,此时name为远程shell方式运行时的目标目录
<!--<remote ip="192.168.8.39" name="tongbu"/>-->
<!--<remote ip="192.168.8.40" name="tongbu"/>-->
</localpath>
<rsync>
<commonParams params="-artuz"/> # 指定rsync选项
<auth start="true" users="rsyncuser" passwordfile="/etc/rsync.pas"/> #修
改此行为true,指定备份服务器的rsync配置的用户和密码文件
<userDefinedPort start="false" port="874"/><!-- port=874 -->#指定rsync的非
标准端口号
<timeout start="false" time="100"/><!-- timeout=100 -->
<ssh start="false"/> #默认使用rsync daemon运行rsync命令,true为使用远程shell模
式
</rsync>
<failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/><!--default every
60mins execute once--> #错误重传及日志文件路径(自定义路径)
<crontab start="false" schedule="600"><!--600mins--> #不开启crontab功能
<crontabfilter start="false"> #不开启crontab定时传输的筛选功能
<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>
<修改后>(软件、rsync服务器、客户端、服务器共享文件(DEST)、客户端存放wordpress资源的目录(SRC)、存放虚拟账号的文件都已完妥当直接在配置文件中套入即可)
<?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="true"/>
<modify start="false"/>
</inotify>
<sersync>
<localpath watch="/data/wordpress/"> #同步wordpress目录下的文件
<remote ip="10.0.0.40" name="wp_backup"/>
<!--<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="cql" passwordfile="/etc/rsync.pas"/>
<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>
4.启动sersyncPS(以后台运行,与终端脱离关系=退出终端该进程不会关闭仍旧监控),sersync一定要加入到PATH中否则会出现无法找到该文件错误。
sersync2 -dro /usr/local/sersync/confxml.xml
1)测试1,发表文件(上传资源),看SRC是否能够同步到DEST下。
2)测试2,被inotify监控的情况下在SRC中修改文件名(会被监控下来通过rsync拷贝至DEST但DEST不会将旧文件delete<也就是重复events>),而采用了sersync后再进行修改则不会出现这种情况。
posted on 2021-07-14 11:42 1251618589 阅读(7) 评论(0) 编辑 收藏 举报