通过rsync+inotify实现实时数据同步

rsync

rsync(Remote Sync)是一个开源的快速备份工具,可以在不同主机之间镜像同步整个目录树,支持增量备份,并保持链接和权限,且采用优化的同步算法,传输前执行压缩,因此非常使用与异地备份、镜像服务器等应用。在远程同步任务重,负责发起rsync同步操作的客户机称为发起端,二负责响应来自客户机的rsync同步操作的服务器称为同步源。在同步过程中,同步源负责提供文件的原始位置,发起端应对该位置具有读取权限。

命令参数

常用参数

参数说明
-vverbose 详细输出
-a归档模式,递归方式传输文件,并保持连接,权限,用户和组,时间信息
-z压缩文件传输
-hhuman-readable, 输出友好
-u跳过已经存在的文件,备份更新
-r–recursive 对子目录以递归模式处理
–delete删除那些 DST 中 SRC 没有的文件
-p–perms 保持文件权限

所有参数

参数说明
-v–verbose 详细模式输出
-q–quiet 精简输出模式
-c–checksum 根据校验和(而不是文件大小、修改时间)来决定是否跳过文件
-a–archive 归档模式,表示以递归方式传输文件,并保持所有文件属性,等于 -rlptgoD
-r–recursive 对子目录以递归模式处理
-R–relative 使用相对路径信息
-b–backup 创建备份,也就是对于目的已经存在有同样的文件名时,将老的文件重新命名为~filename。可以使用 –suffix 选项来指定不同的备份文件前缀。
–backup-dir将备份文件(如~filename) 存放在在目录下。
-suffix=SUFFIX定义备份文件前缀
-u–update 仅仅进行更新,也就是跳过所有已经存在于 DST,并且文件时间晚于要备份的文件。(不覆盖更新的文件)
-l–links 保留软链结
-L–copy-links 想对待常规文件一样处理软链结
–copy-unsafe-links仅仅拷贝指向 SRC 路径目录树以外的链结
–safe-links忽略指向 SRC 路径目录树以外的链结
-H–hard-links 保留硬链结
-p–perms 保持文件权限
-o–owner 保持文件属主信息
-g–group 保持文件属组信息
-D–devices 保持设备文件信息
-t–times 保持文件时间信息
-S–sparse 对稀疏文件进行特殊处理以节省 DST 的空间
-n–dry-run 现实哪些文件将被传输
-W–whole-file 拷贝文件,不进行增量检测
-x–one-file-system 不要跨越文件系统边界
-B–block-size=SIZE 检验算法使用的块尺寸,默认是 700 字节
-e–rsh=COMMAND 指定使用 rsh、ssh 方式进行数据同步
–rsync-path=PATH指定远程服务器上的 rsync 命令所在路径信息
-C–cvs-exclude 使用和 CVS 一样的方法自动忽略文件,用来排除那些不希望传输的文件
–existing仅仅更新那些已经存在于 DST 的文件,而不备份那些新创建的文件
–delete删除那些 DST 中 SRC 没有的文件
–delete-excluded同样删除接收端那些被该选项指定排除的文件
–delete-after传输结束以后再删除
–ignore-errors及时出现 IO 错误也进行删除
–max-delete=NUM最多删除 NUM 个文件
–partial保留那些因故没有完全传输的文件,以是加快随后的再次传输
–force强制删除目录,即使不为空
–numeric-ids不将数字的用户和组 ID 匹配为用户名和组名
–timeout=TIME IP超时时间,单位为秒
-I–ignore-times 不跳过那些有同样的时间和长度的文件
–size-only当决定是否要备份文件时,仅仅察看文件大小而不考虑文件时间
–modify-window=NUM决定文件是否时间相同时使用的时间戳窗口,默认为 0
-T –temp-dir=DIR在 DIR 中创建临时文件
–compare-dest=DIR同样比较 DIR 中的文件来决定是否需要备份
-P等同于 –partial
–progress显示备份过程
-z–compress 对备份的文件在传输时进行压缩处理
–exclude=PATTERN指定排除不需要传输的文件模式
–include=PATTERN指定不排除而需要传输的文件模式
–exclude-from=FILE排除 FILE 中指定模式的文件
–include-from=FILE不排除 FILE 指定模式匹配的文件
–version打印版本信息

安装

服务端(同步源)

  1. 安装rsync
[root@openresty-dev ~]# dnf -y install rsync
  1. 创建用户
[root@openresty-dev ~]# useradd rsync -s /sbin/nologin 
  1. 创建同步目录
[root@openresty-dev ~]# mkdir  /data/webfile
[root@openresty-dev ~]# chown -R rsync:rsync /data/webfile
  1. 修改配置文件
[root@openresty-dev ~]# vim /etc/rsyncd.conf
# RSYNC Config
# 指定传输文件使用的用户
uid = rsync
# 指定传输文件使用的用户组
gid = rsync
# 安全设置,切换到安全目录
use chroot = yes
# 最大连接数
max connections = 10
# 客户端超时时间,单位秒,设置为 0 不超时
timeout = 900
# PID 文件
pid file = /var/run/rsyncd.pid
# 锁文件
lock file = /var/run/rsync.lock
# 日志文件
log file = /var/log/rsyncd.log
# 日志记录方式
transfer logging = yes
# 忽略文件
exclude = lost+found/
# 忽略不可读文件
ignore nonreadable = yes
# 传输时不压缩的文件
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
# 现在的版本需要添加,保留文件的完整属性
fake super = yes

# 模块
[data]
    # 对应的目录
    path = /data/webfile
    # 传输的删除时忽略 I/O 错误,报错会跳过--delete
    ignore errors
    # 允许写入
    read only = false
    # 不允许列出
    list = false
    # 允许的网段,多个使用空格隔开
    hosts allow = 192.168.3.0/24
    # 拒绝的网段,拒绝所有
    hosts deny = 0.0.0.0/32
    # 连接的虚拟用户,非系统用户
    auth users = rsuser
    # 虚拟用户的账号密码文件
    secrets file = /etc/rsuser.password
    # 注释说明
    comment = Test file share
  1. 创建密码文件
[root@openresty-dev ~]# echo "ruser:123456" > /etc/rsuser.password
[root@openresty-dev ~]# chmod 600 /etc/rsuser.password
  1. 启动服务
[root@openresty-dev ~]# rsync --daemon
[root@openresty-dev ~]# ss -tlunp | grep 873
[root@openresty-dev data]# ss -anptu | grep 873
tcp   LISTEN 0      5                                0.0.0.0:873       0.0.0.0:*     users:(("rsync",pid=4193,fd=5))                      
tcp   LISTEN 0      5                                   [::]:873          [::]:*     users:(("rsync",pid=4193,fd=6))     

客户端(被同步端)

  1. 安装rsync
[root@docker ~]#  dnf -y install rsync
  1. 创建密码验证文件
# 注意客户端上面的密码文件中,不需要写用户名,直接写密码就可以了。
[root@docker ~]#  echo "123456" > /etc/rsuser.password
[root@docker ~]#  chmod 600 /etc/rsuser.password
  1. 测试同步
# 同步远程文件到本地 (Pull)
root@docker ~]# rsync -av --password-file=/etc/rsuser.password rsuser@192.168.3.19::data  /data/webfile
receiving incremental file list
created directory /data/webfile
./
1.txt

sent 50 bytes  received 121 bytes  342.00 bytes/sec
total size is 0  speedup is 0.00

# 同步本地文件到远端 (Push)
[root@docker ~]# rsync -arvz --password-file=/etc/rsuser.password docker.svr.test rsuser@192.168.3.19::data
sending incremental file list
docker.svr.test

sent 109 bytes  received 43 bytes  101.33 bytes/sec
total size is 0  speedup is 0.00

inotify 介绍及应用

inotify 是一种强大的、细粒度的、异步文件系统监控机制,内置于Linux内核 2.6.13 及以上版本。为了使用这一内核功能,用户需要配合相应的工具,通常需要用户空间的软件调用才能实现,实现inotify软件有inotify-toolssersynclrsyncd

inotify-tools 是实现 inotify 的一个常用软件包,主要包含两个工具:

在使用 inotify-tools 时,首先需要开启 inotify 进程,该进程将实时监控目标目录的变化情况,并根据设置通过 rsync 命令立即同步至服务器。要实现 inotify 的实时监控,必须先成功配置并验证 rsync 服务的推送功能。

安装

[root@docker ~]# dnf install -y inotify-tools

内核调优

[root@docker ~]#  vim /etc/sysctl.conf #添加以下代码
fs.inotify.max_queued_events = 16384    
# 监控事件队列;
# 表示调用inotify_init时分配给instance中可排队的
# event的数目的最大值,超出这个值的事件被丢弃,但会
# 触发IN_Q_OVERFLOW事件
fs.inotify.max_user_instances = 128     
# 最多监控实例数;
# 表示每一个真实用户ID可创建的instatnces的数量上限
fs.inotify.max_user_watches = 524288   
# 每个实例最多监控目录数;
# 表示每个instatnces可监控的最大目录数量,如果监控
# 的文件数目巨大,需要根据情况,适当增加此值的大小

触发脚本

[root@docker ~]# vim inotify.sh
#!/bin/sh
srcdir=/data/webfile
dstdir=/data/webfile
rsyncuser=rsuser
rsyncpassdir=/etc/rsuser.password
dstip="192.168.3.19"
for ip in $dstip
do
    rsync -avH --port=873 --progress --delete $srcdir $rsyncuser@$ip::$dstdir --password-file=$rsyncpassdir
done
    /usr/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $srcdir | while read file
do
 
    for ip in $dstip
    do
        rsync -avH --port=873 --progress --delete $srcdir $rsyncuser@$ip::$dstdir --password-file=$rsyncpassdir
        echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
    done
done

[root@docker ~]# chmod a+x inotify.sh
[root@docker ~]# nohup inotify.sh  &