对于数据库来说,可以通过主从同步的方式同步数据,那么如果需要普通文件的备份,那么如何进行主从同步那,一般通过rsync和inotify组合文件同步。
一 rsync和inotify 简介
rsynv 远程同步工具,可以对远程服务器进行全量和增量备份同步,同步的数据的时候,rsync采用核心算法对远程服务器的目标文件进行对比,只进行差异同步,如果服务器的文件数量很多,比对耗时很长,发生变化的往往是很少部分,所以一般结合inotify 进行文件同步。
rsynv 可以同步本地的文件夹,也可以进行本地文件夹和远程服务器的同步,类似scp命令;同步本机的不同目录的时候可以进行增量拷贝,所以优于普通的cp命令;rsynv同样可以实现rm功能,来删除目录和文件。
工作场景:
1.两台服务器之间数据同步
2.把所有客户服务器数据同步到备份服务。
3 rsync结合inotify功能做实时数据同步.
安装如下:
yum install rsync
yum install inotify-tools
二 rsync用法简介
rsync 三种用法如下:
Local: rsync [OPTION...] SRC... [DEST]
Access via remote shell:
Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
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
2.1. 本地模式
类似于cp命令,简单的测试下如下:
#建立如下的目录结构:
[root@VM-0-2-centos data]# tree ./
./
|-- dst
`-- src
`-- abc.txt
执行同步命令:
#因为要同步目录所以加-r不然会忽略的.
rsync -r ./src ./dst
结果:
tree ./
./
|-- dst
| `-- src
| `-- abc.txt
`-- src
`-- abc.txt
第一次执行和我预期不一样,将src目录直接同步到dst下面了,我是想把src的文件同步到dst下面,可以执行如下命令:
[root@VM-0-2-centos data]# rsync -r ./src/ ./dst
[root@VM-0-2-centos data]# tree ./
./
|-- dst
| |-- abc.txt
| `-- src
| `-- abc.txt
`-- src
`-- abc.txt
这次就ok了.
简单来说,注意同步的目录还是目录下面的内容,如果下面的内容需要再目录后面加/,如果需要同步整个目录则不需要加/
2.2 远程模式类似scp
简单的测试下:
rsync -iavz ./dst root@xx.xx.xx.xx:/data
The authenticity of host 'xx.xx.xx.xx (xx.xx.xx.xx)' can't be established.
ECDSA key fingerprint is SHA256:9PnqwKNipP7Rtab2Mmy3qXzyaVsnb9G43UtFi+HDLRk.
ECDSA key fingerprint is MD5:0f:10:0e:31:7e:ae:e1:60:98:99:5a:63:bd:7c:70:0f.
Are you sure you want to continue connecting (yes/no)? tes
Please type 'yes' or 'no': yes
Warning: Permanently added 'xx.xx.xx.xx' (ECDSA) to the list of known hosts.
root@阿里主机IP's password:
sending incremental file list
cd+++++++++ dst/
<f+++++++++ dst/abc.txt
cd+++++++++ dst/src/
<f+++++++++ dst/src/abc.txt
sent 211 bytes received 66 bytes 8.03 bytes/sec
total size is 0 speedup is 0.00
在远程主机上看下同步结果,选项支持的太多了,先不讲吧.
[root@iZwz90jb8mqajkli0ttrcbZ data]# tree
.
└── dst
├── abc.txt
└── src
└── abc.txt
2.3 rsync daemon 模式
此种模式是客户端和服务器端都采用的rsync应用程序进行同步的方式.此种方式不像远程的方式通过ssh协议实现,这种方式通过"rsync://协议"(端口号为873),进行数据的传输,服务器按照主机名和文件夹名采用:: 方式进行同步.
如果采用ssh结合rsync进行同步,也不是不行,只是同步文件比较多的话,一条条命令去写很麻烦,
而且还存在着排除文件的问题.rsync daemon
方式启动后,完全可以替换ftp服务器,提供url,外部系统可以通过命令查看文件和下载文件.
rsync 启动时候,需要读取配置文件,默认为:/etc/rsyncd.conf, 端口为873.
默认配置如下:
# uid = nobody
# gid = nobody
# use chroot = yes
# max connections = 4
# pid file = /var/run/rsyncd.pid
# exclude = lost+found/
# transfer logging = yes
# timeout = 900
# ignore nonreadable = yes
# dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
# [ftp]
# path = /home/ftp
# comment = ftp export area
有点类似ini文件格式,除了全局变量,还定义了[ftp],在rsync中称为模块,
想要请求模块,客户端使用"rsync user@host::ftp,表示访问user@host
上的/home/ftp目录.
三 rsync常用选项
rsync选项实在太多,看到眼花缭乱的,用的最多的几个选项说明下:
-a 除了同步文件外,还同步权限属性信息.
-r 递归同步目录
-z 传输过程中进行压缩
-v 显示详细操作过程
--delete 是同步的时候保持两个文件夹完全相同,删除目标文件夹中,在源端文件夹没有的文件,保持两个文件夹完全同步.
--exclude 排除文件夹下的特定文件不进行同步,比如--exclude="a/*.txt" 不同步啊目录下的txt类型文件.
-i 输出要传输文件的路径
-n 不实际进行同步,仅仅进行测试.
五 inotifywait 说明
inotify 是细粒度,异步的文件按照系统时间监控机制,Linux内核从2.6.13起加入inotify支持,通过inotify 可以监控文件系统添加,修改,删除,移动等各种事件,利用这个内核接口,将监控到的变化文件同步出来。
在同步的时候,如果仅仅利用rsync会进行大量文件的比较,同步操作不够实时,我们通过inotify将需要同步的文件监听到,再进行同步,将同步算法中的比较时间减少了,提升同步的速度.
#监听 /data/目录中的modify,create,delete,attrib 四种事件
inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib /data/
CREATE /data/1
ATTRIB /data/1
CREATE /data/5
ATTRIB /data/5
DELETE /data/1
DELETE /data/5
# 操作文件
[root@VM-0-2-centos ~]# touch /data/{1,5}
[root@VM-0-2-centos data]#cd /data rm -rf 1 5
inotifywait 参数说明:
-m,–monitor 始终保持事件监听状态
-r,–recursive 递归查询目录
-q,–quiet 只打印监控事件的信息
–excludei 排除文件或目录时,不区分大小写
-t,–timeout 超时时间
–timefmt 指定时间输出格式
–format 指定时间输出格式
-e,–event 后面指定删、增、改等事件
inotifywait events事件说明:
事件名称 事件说明
access 读取文件或目录内容
modify 修改文件或目录内容
attrib 文件或目录的属性改变
close_write 修改真实文件内容
open 文件或目录被打开
moved_to 文件或目录移动到
moved_from 文件或目录从移动
move 移动文件或目录移动到监视目录
create 在监视目录下创建文件或目录
delete 删除监视目录下的文件或目录
delete_self
unmount 卸载文件系统
如果文件太多,还需要对inotify进一步优化:
ll /proc/sys/fs/inotify/
total 0
-rw-r--r-- 1 root root 0 Aug 15 16:53 max_queued_events
-rw-r--r-- 1 root root 0 Aug 15 16:53 max_user_instances
-rw-r--r-- 1 root root 0 Aug 15 16:53 max_user_watches
max_user_watches # 设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)
max_user_instances #设置每个用户可以运行的inotifywait或inotifywatch命令的进程数
max_queued_events #设置inotify实例事件(event)队列可容纳的事件数量
优化参数:
vim /etc/sysctl.conf
fs.inotify.max_queued_events = 32768
fs.inotify.max_user_instances = 1024
fs.inotify.max_user_watches = 90000000
:q
# 执行生效
sysctl -p
六 实际同步操作
实际工作中,如何利用rsync进行数据同步那,一般分为两种:
-
利用rsync daemon 模式进行数据的同步:(也可以结合inotify)
优点 : 1) 支持多个目录复杂的同步(比如排除特定文件)
缺点: 1) 配置比较繁琐 2) 大量文件需要同步的话无法保证实时 -
利用rsync 和inotify
优点: 1)大量文件下可以进行快速实时同步;
缺点: 1) 多个文件夹同步写的脚本也挺麻烦
假如我们有如下图的同步要求,要求尽可能实时同步,机器重启后仍然可以同步 :
同步要求
6.1 采用rsync和inotify方式进行文件夹数据同步
本次例子采用方式用rsync进行每2个小时进行一次全量同步,平时通过一个shell脚本进行实时同步.
- 首先如图在B主机上建好目录结构和要同步的测试文件信息等:
[root@iZwz90jb8mqajkli0ttrcbZ /]# tree ./testsync/
./testsync/
├── a.txt
├── b.txt
└── c
└── d.txt
在A主机上建好同步目录:
testsync_bak
- 在A主机上拉取命令
一般情况下pull比push要好一些,
[root@VM-0-2-centos /]# rsync -avzP root@B阿里云IP:/testsync/ /testsync_bak
root@B阿里云IP's password:
receiving incremental file list
./
a.txt
0 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=3/5)
b.txt
0 100% 0.00kB/s 0:00:00 (xfr#2, to-chk=2/5)
c/
c/d.txt
0 100% 0.00kB/s 0:00:00 (xfr#3, to-chk=0/5)
sent 92 bytes received 256 bytes 27.84 bytes/sec
total size is 0 speedup is 0.00
看下同步效果:
[root@VM-0-2-centos /]# tree testsync_bak/
testsync_bak/
|-- a.txt
|-- b.txt
`-- c
`-- d.txt
如果要删除testsync_bak 中可能多余的文件,添加--delete即可.
- 做成crontab
由于每次变化都要重新同步文件,比较麻烦,所以需要做成crontab定时去同步文件,定时同步文件,就不能输入密码, 可以通过一个文件来指定密码.
这种通过ssh同步方式,只能做成ssh免密码登录才可以,步骤如下:
- 生成公钥
ssh-keygen -t rsa
一路回车即可.
- 将公钥拷贝到服务器上
ssh-copy-id -i ~/.ssh/id_rsa.pub root@B阿里云IP
如果ssh 登录端口不是22
需要再/root/.ssh下新建config文件,内容为:
Port 20222
- 在测试的同步的时候就不需要密码了
crontab -e
输入同步命令:
* */2 * * * rsync -avz root@B阿里云IP:/testsync/ /testsync_bak
如果只做简单的文件同步,到此就结束了,这是最简单的方式了.
- 支持实时同步
我们上面做rsync进行同步的时候,如果文件多了不够实时,如果做到实时,可以对文件修改,新建等操作进行监控,然后我们根据监控命令触发部分文件的同步,这样我们再结合2个小时的实时文件同步,就可以完美支持大批量文件的实时同步了,找到网上一个脚本改下:
- 首先脚本应该在阿里B主机上建立,因为要监听的是B机器上的文件夹的变化.
- 监控脚本如下,名为:test.sh
#!/bin/bash
SRC=/testsync/
DST=root@阿里B的IP:/testsync_bak
inotifywait -mrq -e create,move,delete,modify,attrib $SRC | while read a b c
do
echo "$c change's so start to rsync"
rsync -azP --delete $(dirname ${c}) $DST
done
- 按照上面方法,设置B主机到A主机的免登陆功能
- 执行程序,后台实时监控:
sh test.sh
我们通过日志方便看到了文件的同步情况.
总结: 通过这种基于ssh的rsync操作完成了数据的同步,对于简单的场景,是适合的,如果需要同时同步多个目录,不是特别合适,不过我仍然喜欢这种方式,简单.
6.2 rsync daemon结合inotify同步
- 在腾讯A主机上配置
vim /etc/rsyncd.conf
port=873
address =0.0.0.0
uid = root
gid = root
use chroot = yes
max connections = 5
pid file =/var/run/rsync.pid
lock file =/var/run/rsync.lock
log file =/var/log/rsyncd.log
motd file =/etc/rsyncd.motd
use chroot = no
timeout = 300
dont compress = *.gz *.tgz *.zip *.bz2
[testsync_bak]
path =/testsync_bak
comment = xxxxx
read only = false
list = yes
hosts allows = 腾讯A机器IP/32
hosts deny = 0.0.0.0/32
auth users = rsync_user # 同步的用户
secrets file= /root/rsync.passwd # 同步的用户密码文件
- 设置密码文件
vim /root/rsync.passwd
rsync_user:123@345 #用户名:密码
更改权限:
chmod 600 /etc/rsync.passwd
- 启动服务加入到启动项中
rsync --daemon --config=/etc/rsyncd.conf
报错:
2021/08/15 20:39:02 [4005270] rsyncd version 3.1.3 starting, listening on port 873
2021/08/15 20:39:02 [4005270] bind() failed: Cannot assign requested address (address-family 2)
2021/08/15 20:39:02 [4005270] unable to bind any inbound sockets on port 873
绑定地址改成address =0.0.0.0
就好。
- 在阿里B机器上进行同步
rsync -avz /testsync rsync_user@腾讯云AIP::testsync_bak --password-file=/root/rsync.passwd
报错:
rsync: failed to connect to 腾讯A主机 ( 腾讯A主机): No route to host (113)
rsync error: error in socket IO (code 10) at clientserver.c(127) [sender=3.1.3
关闭防火墙就是:
systemctl stop firewalld
报错:
@ERROR: auth failed on module testsync_bak
注意要检查字段名配置是否正确,chmod 600 /etc/rsync.passwd 通过命令要更改权限,不然还是会校验失败。
报错:
for rsync_user: password mismatch
原因:
rsync -avz /testsync rsync_user@腾讯云AIP::testsync_bak --password-file=/root/rsync.passwd
/root/rsync.passwd 里面只要包含密码就行了。
把这个命令放在crontab里面即可,或写个sh放在crontab中。
inotify结合
网上找个脚本稍微更改了下:
#!/bin/bash
src=/testsync/ # 需要同步的源路径
des=testsync_bak # 目标服务器上 rsync --daemon 发布的名称,rsync --daemon这里就不做介绍了,网上搜一下,比较简单。
rsync_passwd_file=/root/rsync.passwd # rsync验证的密码文件
ip1=腾讯A机器IP # 目标服务器1
user=rsync_user # rsync --daemon定义的验证用户名
cd ${src}
# 此方法中,由于rsync同步的特性,这里必须要先cd到源目录,inotify再监听 ./ 才能rsync同步后目录结构一致,有兴趣的同学可以进行各种尝试观看其效果
inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib,close_write,move ./ | while read file
# 把监控到有发生更改的"文件路径列表"循环
do
INO_EVENT=$(echo $file | awk '{print $1}') # 把inotify输出切割 把事件类型部分赋值给INO_EVENT
INO_FILE=$(echo $file | awk '{print $2}') # 把inotify输出切割 把文件路径部分赋值给INO_FILE
echo "-------------------------------$(date)------------------------------------"
echo $file
#增加、修改、写入完成、移动进事件
#增、改放在同一个判断,因为他们都肯定是针对文件的操作,即使是新建目录,要同步的也只是一个空目录,不会影响速度。
if [[ $INO_EVENT =~ 'CREATE' ]] || [[ $INO_EVENT =~ 'MODIFY' ]] || [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]] ||[[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]]
then
echo 'CREATE or MODIFY or CLOSE_WRITE or MOVED_TO'
rsync -avzcR --delete --password-file=${rsync_passwd_file} $(dirname ${INO_FILE}) ${user}@${ip1}::${des}
# INO_FILE变量代表路径哦 -c校验文件内容
fi
#修改属性事件 指 touch chgrp chmod chown等操作
if [[ $INO_EVENT =~ 'ATTRIB' ]]
then
echo 'ATTRIB'
if [ ! -d "$INO_FILE" ]
# 如果修改属性的是目录 则不同步,因为同步目录会发生递归扫描,等此目录下的文件发生同步时,rsync会顺带更新此目录。
then
rsync -avzcR --password-file=${rsync_passwd_file} $(dirname ${INO_FILE}) ${user}@${ip1}::${des}
fi
fi
done
运行:
测试运行
总结: 用配置文件的方式还是挺费劲的,好处是不用设置ssh免登录。
七 参考链接
[rsync 用法教程](http://www.ruanyifeng.com/blog/2020/08/rsync.html)
[rsync(一):基本命令和用法](https://blog.csdn.net/qq_32706349/article/details/91451053)
[真正的inotify+rsync实时同步 彻底告别同步慢](http://www.ttlsa.com/web/let-infotify-rsync-fast/)
网友评论