5

数据实时同步

在生产中有一种需求是,当目录下的文件数据发生变化时,就将数据备份到备份服务器上。实现这样的需求需要做到以下两点:

  • 利用监控服务(inotify),监控到要同步服务器的目录文件的变化
  • 发现目录数据发生变化就利用rsync服务将数据发送到备份服务器

因此,利用rsync+inotify可实现数据的实时同步。

Inotify介绍

Inotify是一种强大的,细粒度的。异步的文件系统事件监控机制,linux内核从2.6.13起,加入了 Inotify支持,通过Inotify可以监控文件系统中添加、删除,修改、移动等各种事件,利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而 inotify-tools 正是实施这样监控的软件。

Inotify实际是一种事件驱动机制,它为应用程序监控文件系统事件提供了实时响应事件的机制,而无须通过诸如cron等的轮询机制来获取事件。cron等机制不仅无法做到实时性,而且消耗大量系统资源。相比之下,inotify基于事件驱动,可以做到对事件处理的实时响应,也没有轮询造成的系统资源消耗,是非常自然的事件通知接口,也与自然世界事件机制相符合。

Inotify安装

环境介绍

[root@moli-linux03 ~] uname -r
3.10.0-862.2.3.el7.x86_64
[root@moli-linux03 ~] cat /etc/redhat-release 
CentOS Linux release 7.5.1804 (Core)

安装前提
需要2.6.13以后内核版本才能支持inotify软件。2.6.13内核之后版本,在没有安装inotify软件之前,应该有这三个文件。

[root@moli-linux03 ~] ll /proc/sys/fs/inotify/
总用量 0
-rw-r--r--. 1 root root 0 2月   3 12:24 max_queued_events
-rw-r--r--. 1 root root 0 2月   3 12:24 max_user_instances
-rw-r--r--. 1 root root 0 2月   3 12:24 max_user_watches
[root@moli-linux03 ~] 

三个文件的说明

文件 默认值 作用说明
max_user_watches 8192 设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)
max_user_instances 128 设置每个用户可以运行的inotifywait或inotifywatch命令的进程数
max_queued_events 16384 设置inotify实例事件(event)队列可容纳的事件数量

注:可以将三个文件的数值调大,监听更大的范围

安装方式
可选择yum安装或者编译安装,yum安装需要配置有epel源,编译安装需要到github下载源码包。
yum安装

yum install -y inotify-tools

编译安装(源码包地址:https://github.com/rvoicilas/...

tar -zxf  tar -zxf inotify-tools-3.13.tar.gz 
./configure
make
make install

inotify主要安装的两个软件
inotifywait: (主要)
  在被监控的文件或目录上等待特定文件系统事件(open close delete等)发生,执行后处于阻塞状态,适合在shell脚本中使用
inotifywatch
  收集被监控的文件系统使用的统计数据,指文件系统事件发生的次数统计。
  说明:在实时实时同步的时候,主要是利用inotifywait对目录进行监控

inotifywait重要命令参数说明

参数 说明
-m 始终保持事件监听
-r 递归监控目录数据信息变化
-q 输出信息少(只打印事件信息)
-timefmt 指定时间输出格式
-format 打印使用指定的输出类似格式字符串;即实际监控输出内容
-e 指定监听指定的事件,如果省略,表示所有事件都进行监听

-e[参数] 可以指定的事件类型

事件名称 说明
close_write 文件或目录关闭,在写入模式打开之后关闭的。
move 文件或目录不管移动到或是移出监控目录都触发事件
create 文件或目录创建在监控目录中
delete 文件或目录被删除在监控目录中

示例测试
对一个服务器打开两个终端窗口,终端1执行创建,删除,修改,移动文件等操作,终端2执行inotifywait命令。
创建事件

[root@终端2 ~] inotifywait -mrq  /root/rsync_test --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件信息: %e" -e create
[root@终端1 rsync_test]# touch 1.txt
下面显示出事件信息,在终端一执行创建文件操作之后终端二才显示的事件
03-02-19 12:48 /root/rsync_test/1.txt 事件信息: CREATE

删除事件

[root@moli_linux1 ~]#  inotifywait -mrq  /data --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件信息: %e" -e delete
[root@moli_data ~]# rm -f 1.txt

修改事件

[root@moli_linux1 ~]# inotifywait -mrq  /data --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件信息: %e" -e close_write
[root@moli_data ~]# echo "hahaha"  > 2 .txt

移动事件move_to
把其他目录文件移动到监控目录

[root@moli_linux1 ~]#  inotifywait -mrq  /data --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件信息: %e" -e moved_to
[root@moli_data ~]# mv /etc/passwd .

移动事件move_from
把监控目录文件移到其他目录

[root@moli_linux1 ~]# inotifywait -mrq  /data --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件信息: %e" -e moved_from
[root@moli_data ~]# mv 2.txt /tmp   

inotifywait --timefmt时间参数说明

命令参数 说明
%y 年份信息,显示信息为十进制,并且没有世纪信息
%m 显示月份,显示信息为十进制(范围 01-12 )
%d 每月的第几天,显示倍息为十进制数(范围是 01-31 )
%H 小时信息,显示信息为十进制,使用 24小时制(范围 00-23 )
%M 显示分钟,显示信息为十进制(范围 00-59 )

inotifywait --format参数说明

命令参数 说明
%w 事件出现时,监控文件或目录的名称信息
%f 事件出现时,将显示监控目录下触发事件的文件或目录信息,否则为空
%e 显示发生的事件信息,不同的事件信息用逗号进行分隔
%T 输出时间格式中定义的时间格式信息,通过 --timefmt option 语法格式指定时间信息这个格式是通过strftime函数进行匹配时间格式信息的

Linux文件同步工具rsync

介绍

rsync是一款开源,快速,多功能的可实现增量的本地或远程的数据镜像同步备份的优秀工具。适用于多个平台。从软件名称可以看出来是远程同步的意思(remote sync)。可使本地主机不同分区或目录之间及本地和远程两台主机之间的数据快速同步镜像,远程备份等功能。

在同步备份时,默认情况下,rsync通过其独特的“quick check”算法,仅同步大小或者最后修改时间发生变化的文件或目录(也可根据权限,属主等变化同步,需要制定参数)。甚至是只同步一个文件里变化的内容部分,所以可以实现快速的同步数据的功能。

提示:传统的cp,scp工具拷贝每次均为完整拷贝,而rsync除了完整拷贝,还具备增量拷贝的功能,因此从此性能及效率上更胜一筹。

Rsync的特性
1)支持拷贝特殊文件如链接,设备等
2)可以有排除指定文件或目录同步的功能,相当于打包命令tar
3)可以保持原来文件或目录的权限,时间,软硬链接等所有属性均不改变。
4)可实现增量同步,即只同步发生变化的数据,因此数据传输效率更高
5)可以使用rcp,rsh,ssh等方式来配合传输文件,也可以通过直接的socker链接
6)支持匿名的或认证的进程模式传输,方便进行数据备份及镜像。

核心算法介绍
假定在名为α和β的两台计算机之间同步相似的文件 A 与 B ,其中α对文件 A 拥有访问权,β对文件 B 拥有访问权。并且假定主机α与β之间的网络带宽很小。那么 rsync 算法将通过下面的五个步骤来完成:

  1. β将文件 B 分割成一组不重叠的固定大小为 S 字节的数据块。最后一块可能会比 S 小。
  2. β对每一个分割好的数据块执行两种校验:一种是 32 位的滚动弱校验,另一种是 128 位的 MD4 强校验。
  3. β将这些校验结果发给α。
  4. α通过搜索文件 A 的所有大小为 S 的数据块 ( 偏移量可以任选,不一定非要是 S 的倍数 ) ,来寻找与文件 B 的某一块有着相同的弱校验码和强校验码的数据块。这项工作可以借助滚动校验的特性很快完成。
  5. α发给β一串指令来生成文件 A 在β上的备份。这里的每一条指令要么是对文件 B 经拥有某一个数据块而不须重传的证明,要么是一个数据块,这个数据块肯定是没有与文件 B 的任何一个数据块匹配上的。

结论:rsync就是会同步我们指定的两端目录之间的数据,这个数据可以是特殊的数据。同步之前就先进行两端的数据的比对,只会同步两者之间不同的部分,并保留文件原本的属性。并且支持匿名的方式进行同步传输。所以rsync在备份,同步上就会较为快速。
rsync命令常用选项

选项 说明
-a(重要) 包含-rtplgoD选项
-r(重要) 同步目录时要加上,类似cp命令的-r选项
-v(重要) 同步时显示一些信息,让我们知道同步的过程
-l 保留软链接
-L 同步软链接时会把源文件给同步
-p 保持文件的权限属性
-o 保持文件的属主
-g 保持文件的属组
-D 保持设备文件信息
-t 保持文件的时间属性
--delete 删除DEST中SRC没有的文件
--exclude 过滤指定文件,如--exclude "logs" 会把文件名包含logs的文件或者目录过滤掉,不同步
-p 显示同步过程,比如速率,比-v更加详细
-u 如果DEST中的文件比SRC新,就不会同步
-z 传输时压缩

rsync的简单示例

示例1 将目录下1.txt拷贝到本目录下的2.txt
在本地里使用rsync就类似于cp命令,rsync == cp

[root@moli-linux03 rsync_test]# ls
1.txt
[root@moli-linux03 rsync_test]# rsync -av 1.txt 2.txt
sending incremental file list
1.txt

sent 87 bytes  received 35 bytes  244.00 bytes/sec
total size is 0  speedup is 0.00
[root@moli-linux03 rsync_test]# ls
1.txt  2.txt

示例2 把/etc/passwd文件拷贝到远程主机的/tmp目录下,并改名叫1.txt

rsync -av /etc/passwd root@192.168.199.7:/tmp/1.txt

示例3 通过ssh同步,指定端口号
rsync == scp

rsync -av -e "ssh -p 22" /etc/passwd 192.168.199.3:/tmp/test

通过服务进行文件同步

rsync也可以通过启动守护进程方式来同步数据,需要有服务端和客户端。
4.1 环境准备

ip 说明
192.168.30.5 rsync服务端
192.168.30.6 rsync客户端

4.2 服务端配置
① 编辑rysnc配置文件vim /etc/rsyncd.conf,配置内容如下:

uid = rsync
gid = rsync
use chroot = no
max connections = 200
timeout = 300
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
hosts allow = 192.168.30.0/24
auth users = rsync_backup
secrets file = /etc/rsync.passwd
[backup]
comment = "backup dirtory"
path = /root/rsync_test

② 创建用户

useradd -s /sbin/nologin -M rsync

③ 创建同步数据目录,授权属主

 mkdir rsync_test
 chown -R rsync.rsync rsync_test/

④ 创建用户认证密码文件,权限600

touch /etc/rsync.passwd
echo "rsync_backup:syushin" > /etc/rsync.passwd
chmod 600 /etc/rsync.passwd

⑤ 启动rsync服务

rsync --daemon

⑥查看进程

ps aux | grep rsync
netstat -lntp | grep rsync

4.3 rsync客户端配置
① 检查rsync是否有安装

rpm -qa | grep rsync

如果没有执行安装即可。

② 创建安全认证文件(客户端的认证文件只需要有密码即可),授权600

touch /etc/rsync.passwd
echo "syushin" > /etc/rsync.passwd
chmod 600 /etc/rsync.passwd

③ 推(push)文件测试
将客户端文件motd同步到服务端中backup定义的同步数据目录下,并改名叫test.txt
交互式:

rsync -avP /etc/motd rsync_backup@192.168.30.5::backup/test.txt

非交互式:

rsync -avP /etc/motd rsync_backup@192.168.30.5::backup/test.txt --password-file=/etc/rsync.passwd  

⑤ 拉(pull)文件测试
把服务端同步数据目录中的test.txt文件同步到本地的tmp目录下,并改名叫server-file.txt

rsync -avP rsync_backup@192.168.30.5::backup/test.txt /tmp/server-file.txt --password-file=/etc/rsync.passwd 

4.4 rsync启动脚本
通过上面步骤可知rsync启动使用rsync --daemon命令,关闭则需要手动kill掉,这样对于管理rsync来说非常不方便,因此这里通过shell写一个rsync管理脚本。脚本内容如下:

vim /etc/init.d/rsyncd

#!/bin/bash
# chkconfig: 2345 20 80
# desription: Rsync Startup scripts by oldboy
. /etc/init.d/functions

function usage(){
    echo $"usage:$0 {start|stop|restart}"
    exit 1
}

function start(){
    rsync --daemon
    sleep 1
    if [ `netstat -lntp | grep rsync | wc -l` -ge 1 ]
      then
          action "Rsyncd is started." /bin/true
    else
        action "Rsyncd is started." /bin/false
    fi
}

function stop(){
    killall rsync &>/dev/null
    sleep 2
    if [ `netstat -lntp|grep rsync|wc -l` -eq 0 ]
      then
       action "rsyncd is stopped." /bin/true
    else
      action "rsyncd is stopped." /bin/false
    fi
}

function main(){
    if [ $# -ne 1 ]
      then
       usage
    fi
    if [ "$1" == "start" ]
      then
          start
    elif [ "$1" == "stop" ]
      then
          stop
    elif [ "$1" == "restart" ]
      then
         stop
         sleep 1
         start
    else
     usage
    fi
}
main $*

授予脚本可执行权限

chmod +x /etc/init.d/rsyncd

测试,执行脚本,然后通过查看进程判断脚本是否执行成功。

/etc/init.d/rsyncd start
netstat -lntp | grep rsync
ps aux |grep rsync

关于rsyncd.conf配置文件的解释

#设置服务器信息提示文件名称,在该文件中编写提示信息
motd file = /etc/rsyncd.motd

#开启Rsync数据传输日志功能
transfer logging = yes

#设置日志文件名称,可以通过log format参数设置日志格式
log file = /var/log/rsyncd.log

#设置Rsync进程保存文件名称
pid file = /var/run/rsyncd.pid

#设置锁文件名称
lock file = /var/run/rsyncd.lock

#设置服务器监听的端口号,默认是873端口
port = 873

#设置进行数据传输所使用的账户名称或ID号,默认使用nobody
uid = rsync

#设置进行数据传输所使用的组名称或组ID,默认使用nobody
gid = rsync

#设置服务器所监听的IP地址,这里的服务器地址是192.168.30.5
address = 192.168.30.5

#设置user chroot为yes后,rsync首先会进行chroot设置,将根映射到path参数路径下,对客户端而言,系统的根就是path参数所指定的路径。但这样做需要root权限,并且在同步符号连接资料时仅会同步名称,而内容不会同步。
use chroot = no

#是否允许客户端上传数据,这是设置只读
read only = yes

#设置并发连接数,0代表无限制。超出并发数后,如果依然有客户端连接请求,则会收到稍后重试的提示信息。
max connections = 10

#模块,Rsync通过模块定义同步的目录,模块以[name] 的形式定义,在Rsync中也可以定义多个模块
[test]

#comment定义注释说明字串
comment = web content

#同步目录的真实路径通过path指定
path = /root/rsync_test

#exclude 可以指定例外的目录,即将/tmp/rsync目录下的某个目录设置不同步数据
exclude = test/

#设置允许连接服务器的用户,账户可以是不存在的用户
auth users = rsync_backup

#设置密码验证文件名称,注意该文件的权限要求为只读,建议权限600,仅在设置了auth users 后生效
secrets file = /etc/rsync.passwd

#设置允许那些主机可以同步数据,可以是单个IP也可以是一个网段,多个IP之间用空格隔开
hosts allows=192.168.30.5 192.168.30.0/24

#设置拒绝所有,除了hosts allows定义的
hosts deny = *

#客户端请求显示模块列表,本模块名称是否显示,默认为true
list = false

use chroot true|false:表示在传输文件前首先chroot到path参数所指定的目录下。这样做的原因是实现额外的安全防护,但缺点是需要以roots权限,并且不能备份指向外部的符号连接所指向的目录文件。默认情况下chroot值为true,如果你的数据当中有软连接文件,建议你设置成false。

当设置了auth users和secrets file后,客户端连服务端也需要用用户名密码了,若想在命令行中带上密码,可以设定一个密码文件。
rsync -avL test@192.168.133.130::test/test1/ /tmp/test8/ --password-file=/etc/pass 其中/etc/pass内容就是一个密码,权限要改为600

rsync -avP --port 8730 /etc/passwd 192.168.30.5::backup/test.txt
--port可以指定端口。

rsync+inotify相结合,实现文件实时同步

通过上面对inotify和rsync的了解,实现文件实时同步就很简单了。大概流程是利用脚本,先对同步数据的目录进行监控,如果监控到数据发生变化,就执行rsync同步,然后将脚本放到任务计划中执行。
下面是操作步骤.
环境

系统 IP 说明
CentOS7 192.168.30.5 rsync服务端
CentOS7 192.168.30.6 rsync客户端

第一步,部署rsync服务

客户端和服务端都查看是否有安装rsync

rpm -qa | grep rsync

服务端的配置(流程和上面的通过服务同步文件一样,这里再次写上)
① 编辑rysnc配置文件vim /etc/rsyncd.conf,配置内容如下:

uid = rsync
gid = rsync
use chroot = no
max connections = 200
timeout = 300
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
hosts allow = 192.168.30.0/24
auth users = rsync_backup
secrets file = /etc/rsync.passwd
[backup]
comment = "backup dirtory"
path = /root/rsync_test

② 创建用户

useradd -s /sbin/nologin -M rsync

③ 创建同步数据目录,授权属主

 mkdir rsync_test
 chown -R rsync.rsync rsync_test/

④ 创建用户认证密码文件,权限600

touch /etc/rsync.passwd
echo "rsync_backup:syushin" > /etc/rsync.passwd
chmod 600 /etc/rsync.passwd

⑤ 启动rsync服务

rsync --daemon

客户端的配置
① 检查rsync是否有安装

rpm -qa | grep rsync

如果没有执行安装即可。

② 创建安全认证文件(客户端的认证文件只需要有密码即可),授权600

touch /etc/rsync.passwd
echo "syushin" > /etc/rsync.passwd
chmod 600 /etc/rsync.passwd

第二步,部署inotify

服务端和客户端都检查是否安装inotify

rpm -qa |grep inotify-tools

如果没有就执行安装命令

yum install -y inotify-tools

或者手动编译安装,需要源码包
源码包参考地址:https://github.com/rvoicilas/...

  tar -zxf  tar -zxf inotify-tools-3.13.tar.gz 
    ./configure
    make
    make install

至此,inotify安装完成。

第三步,编写脚本实现inotify与rsync相结合

同步数据的操作通常在客户端进行,下面命令都在客户端执行。
rsync同步目录数据命令
将本地data目录数据同步到服务端的同步数据目录中

rsync -avz --delete /data rsync_backup@192.168.30.5::backup --password-file=/etc/rsync.passwd

inotify监控data同步目录数据发生变化命令

inotifywait -mrq /data -format "%w%f"  -e create,delete,move_to,close_write

编写脚本

#!/bin/bash
Path=/root/rsync_data
backup_Server=192.168.30.5

/usr/bin/inotifywait -mrq --format '%w%f' -e create,close_write,delete $Path  | while read line  
do
    if [ -f $line ];then
        rsync -az $line --delete rsync_backup@$backup_Server::backup --password-file=/etc/rsync.passwd
    else
        cd $Path &&\
        rsync -az ./ --delete rsync_backup@$backup_Server::backup --password-file=/etc/rsync.passwd
    fi

done

测试
让脚本后台运行

sh /root/server/scripts/inotify.sh

在同步数据目录创建文件

cd /root/rsync_data
touch {1..6}.txt

在服务端查看文件,已经生成。

[root@moli-linux03 rsync_test]# ls
hh.txt  rsync_data
[root@moli-linux03 rsync_test]# cd rsync_data/
[root@moli-linux03 rsync_data]# ls
1.txt  2.txt  3.txt  4.txt  5.txt  6.txt

至此,实现文件实时同步已经完成。

关于脚本后台运行的相关命令,后续再说。

参考资料

惨绿少年的博客:https://www.cnblogs.com/clsn/...
惨绿少年的博客:https://www.cnblogs.com/clsn/...


syushin
948 声望316 粉丝