zoukankan      html  css  js  c++  java
  • rsync+inotify数据实时同步

    1. rsync概述

    1.1 rsync简介

    • rsync是可以实现增量备份的工具。配合任务计划,rsync能实现定时或间隔同步,配合inotify或sersync,可以实现触发式的实时同步。
    • rsync的目的是实现两端主机之间的文件同步,所有实现的cp、rm、scp等功能只是同步的辅助手段,且rsync对于这些功能的实现方式和和本地的这些命令是不同的。

    1.2 rsync同步过程的模式组成

    1)决定哪些文件需要同步的检查模式

    • 检查模式是按照规则来检查哪些文件需要被同步,以及哪些文件是明确被排除不传输的
    • 默认情况下,rsync使用“quick check”算法快速检查源文件和目标文件的大小、mtime是否一致,如果不一致则需要传输

    2)文件同步时的同步模式

    • 同步模式志在文件确定要被同步后,在同步过程中发生之前要做哪些额外工作,如是否要先删除源主机上没有但目标主机上有的文件、是否要先备份已经存在的目标文件,是否要追踪链接文件等额外操作。

    1.3 rsync的三种工作方式

    • 单个主机本地之间的数据传输(类似于cp命令的功能)
    • 借助rpc、ssh等通道来传输数据(类似于scp命令的功能)
    • 本地主机通过网络套接字连接远程主机上的rsync daemon(让远程主机上运行rsync服务,使其监听在一个端口上,等待客户端的连接)
      • rsync默认监听873/tcp端口

    2. rsync实现数据推送&拉取&筛选

    2.1 rsync本地数据传输

    1)语法规则

    rsync [OPTION...] SRC... [DEST]
    # 第一个路径参数一定是源文件路径(作为同步基准的一方),可以同时制定多个源文件路径
    # 最后一个路径参数是目标文件(待同步的一方)
    # 路径的格式可以是本地路径,也可以是使用user@host:path或user@host::path的远程路径
    # 如果主机和path路径之间使用单个冒号隔开,表示使用的是远程shell通信方式,而使用双冒号隔开的则表示的是连接rsync daemon
    • 如果仅有一个SRC或DEST参数,则将以类似于"ls -l"的方式列出源文件列表(只有一个路径参数,总会认为是源文件),而不是复制文件
    • 源路径如果是一个目录的话,不带尾随斜线表示的是整个目录包括目录本身,带上尾随斜线表示的是目录中的文件,不包括目录本身
    [root@xuexi ~]# rsync /etc/fstab  /tmp                # 在本地同步
    [root@xuexi ~]# rsync -r /etc  172.16.10.5:/tmp       # 将本地/etc目录拷贝到远程主机的/tmp下,以保证远程/tmp目录和本地/etc保持同步
    [root@xuexi ~]# rsync -r 172.16.10.5:/etc  /tmp       # 将远程主机的/etc目录拷贝到本地/tmp下,以保证本地/tmp目录和远程/etc保持同步
    [root@xuexi ~]# rsync /etc/                           # 列出本地/etc/目录下的文件列表
    [root@xuexi ~]# rsync 172.16.10.5:/tmp/               # 列出远程主机上/tmp/目录下的文件列表

    2)使用及参数说明

    # 普通的本地文件的复制
    rsync  源  目标
    
    # 普通的本地文件复制,并保持文件的所有属性(-avz)
    rsync -avz  源  目标
        # 参数说明
                -a  以递归的方式传输数据,并保持文件的所有属性,相当于-lrtopgD
                -v  显示详细信息
                -z  压缩传输
                -r  递归模式
                
                -t  --times,保持文件时间信息
                -o  --owner,保持文件的属主信息
                -p  --perms,保持文件权限
                -g  --group,保持文件属组信息
                -P  --progress,显示同步的过程及传输时的进度等信息
                -D  --devices,保持设备文件信息
                -l   --links,保留软链接信息
    
    # 删除/data/目录中的内容
    rsync  -r  --delete  /null/  /data/
        # null目录要事先创建且为空,其实就是将data目录跟null目录同步
        # 目录后面的那个斜线要加上,如果null中有内容,则会将data目录中的所有内容全部删除之后再进行同步

    2.2 rsync借助ssh通道传输数据

    1)借助ssh通道将数据推送到远端主机

    # 将本地的/etc/hosts文件通过ssh通道推送到远程主机的家目录下
    rsync -avz  /etc/hosts -e "ssh -p 22 -o StrictHostKeyChecking=no" hgzero@10.0.0.202:~
        # 说明:
                -e:表示使用ssh通道/etc/hosts  表示本地要推送的文件
                wzh  表示远程主机的用户名
                IP地址后面的冒号:是指定远程主机接收文件的路径

    2)借助ssh通道从远端主机拉取数据

    # 将远端主机的整个/opt目录拉取到本地的/tmp目录中来
    rsync -avzP  -e  "ssh -p 22"  hgzero@10.0.0.202:/opt  /tmp
        # 说明:
                -P:表示显示同步的过程(--pregress)

    2.3 rsync以守护进程方式传输数据

    1)rsync守护进程daemon模式的配置(rsync服务端的配置)

    • rsync服务的配置文件:/etc/rsync.conf
    ### 全局配置参数
    port=888              # 指定rsync端口,默认873
    uid = rsync           # rsync服务的运行用户,默认是nobody,文件传输成功后属主将是这个uid
    gid = rsync           # rsync服务的运行组,默认是nobody,文件传输成功后属组将是这个gid
    use chroot = no       # rsync daemon在传输前是否切换到指定的path目录下,并将其监禁在内
    max connections = 200 # 指定最大连接数量,0表示没有限制
    timeout = 300         # 如果在这段时间内没有响应,则断开连接,以确保rsync服务器不会永远等待一个崩溃的客户端,0表示永远等待
    motd file = /var/rsyncd/rsync.motd   # 客户端连接过来显示的消息
    pid file = /var/run/rsyncd.pid       # 指定rsync daemon的pid文件
    lock file = /var/run/rsync.lock      # 指定锁文件,以防止多个进程同时修改一个文件产生冲突
    log file = /var/log/rsyncd.log       # 指定rsync的日志文件,而不把日志发送给syslog
    dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2  # 指定哪些文件不用进行压缩传输
     
    ### 指定模块,并设定模块配置参数,可以创建多个模块
    [hgzero]           # 模块ID
    path = /hgzero/    # 指定该模块的路径,类似于nfs的共享目录,该参数必须指定
    # 启动rsync服务前该目录必须存在,rsync请求访问模块本质就是访问该路径
    ignore errors # 忽略某些IO错误信息 read only = false # 指定该模块是否可读写,即能否上传文件,false表示可读写,true表示可读不可写,所有模块默认不可上传 write only = false # 指定该模式是否支持下载,设置为true表示客户端不能下载;所有模块默认可下载 list = false # 客户端请求显示模块列表时,该模块是否显示出来,设置为false则该模块为隐藏模块。默认true hosts allow = 10.0.0.0/24 # 指定允许连接到该模块的机器,多个ip用空格隔开或者设置区间 hosts deny = 0.0.0.0/32 # 指定不允许连接到该模块的机器
    auth users = rsync_backup # 指定连接到该模块的用户列表,只有列表里的用户才能连接到模块,用户名和对应密码保存在secrts file中, # 这里使用的不是系统用户,而是虚拟用户,不设置时,默认所有用户都能连接,但使用的是匿名连接 secrets file = /etc/rsyncd.passwd # 保存auth users用户列表的用户名和密码,每行包含一个username:passwd
    # 由于"strict modes"
    默认为true,所以此文件要求非rsync daemon用户不可读写
    # 只有启用了auth users该选项才有效

    # 定义第二个模块

    [shit] path=/shit/ read only = false ignore errors comment = anyone can access
    • 服务端中rsync服务的启动及后续操作
    rsync  --daemon                    # 启动rsync服务,然后再用lsof  -i  :873检查一下
    useradd  rsync  -s  /sbin/nologin  # 添加一个虚拟用户
    chown  -R  rsync.rsync  /hgzero    # 对共享目录进行授权
    echo "rsync_backup:woshiniba"  > /etc/rsyncd.passwd  # 将用户名和密码添加到文件中,rsync_backup是rsync的虚拟用户名,密码是woshiniba
    chomd  600  /etc/rsyncd.passwd      # 降低密码文件的权限,因为密码是明文的,所以设置600是为了防止其他用户看到密码
    # 关闭防火墙
    # 关闭SELinux

    2)rsync守护进程daemon模式的配置(rsync客户端的配置)

    echo  "woshiniba" > /etc/rsyncd.passwd # 只在密码文件中添加密码,以避免交互式的输入密码
    chmod  600 /etc/rsyncd.passwd          # 设置密码文件的权限

    3)在Client端进行数据的拉取或推送

    • 在client端实现对server端数据的拉取
      # 从hgzero模块中指定的文件路径中将数据拉取到client端的/data目录下
      rsync -avz rsync_backup@10.0.0.101::hgzero /data # rsync_backup代表的是登录的用户 # :: 后面的hgzero表示的配置文件中指定的模块hgzero中对应的path共享路径 # 按照以上配置之后拉取的时候需要手动输入密码,可以添加--password-file参数以自动输入密码
      rsync -avz rsync_backup@10.0.0.101::hgzero /data --password-file=/etc/rsync.password
    • 在client端将数据推送到server端
      # 将本地的/data/目录下的内容推送到远端hgzero模块对应的路径中
      rsync  -avz  /data/  rsync_backup@10.0.0.101::hgzero  --password-file=/etc/rsync.password
        
      # 注意:这里的data一定要写全路径并加上全双下划线,如果这里的hgzero不写的话,默认将推送到指定配置文件的目录中
    • 另外一种数据拉取和推送的方式
      # 1. client端从服务端拉取数据:
      rsync  -avz  rsync://rsync_backup@10.0.0.101/hgzero/   /data  --password-file=/etc/rsync.password 
          # 这里的rsync://是固定写法,后面的hgzer指的是配置文件中指定的目录,可以在这里后接,如  /hgzero/wzh/hg
      
      # 2. client端将数据推送到服务端:    
      rsync  -avz  /data/  rsync://rsync_backup@10.0.0.101/hgzero/  --password-file=/etc/rsync.password

    2.4 对传输的文件进行筛选(排除)

    1)在客户端的排除

    # 描述:
    --exclude=PATTERN    exclude files matching PATTERN      # 以指定的样式进行排除
    --exclude-from=FILE    read exclude patterns from FILE   # 以文件中指定的样式进行排除
    
    # 操作:
    rsync  -avz  --exclude=a  /data/   rsync_backup@10.0.0.101::hgzero   --password-file=/etc/rsync.password      
    # 效果:要传输的文件除了文件名为a的文件
    # 注意:如果要排除多个文件,则可以使用这样的形式:--exclude={a,b,c,d} 传输除了a,b,c,d之外的其他所有文件,或者再写几个--exclude
        
    rsync  -avz  --exclude-from=paichu.log  /data/  rsync_backup@10.0.0.101::hgzero  --password-file=/etc/rsync.password   
    # 效果:在paichu.log这个文件中定义了所有要排除的文件名的pattern样式
    # 注意:这里要先创建paichu.log文件,并在其中定义要排除的文件名的样式

    2)在服务端的排除

    # 1. 在配置文件 /etc/rsyncd.conf  中添加:exclude = a  b  c    (注意这里是以空格隔开)
    
    # 2. 杀死rsync进程
    kill cat `/var/run/rsyncd.pid`
    pkill   rsync
    
    # 3. 启动rsync服务
    rsync    --daemon
    
    # 4. 查看
    ps   -ef  |  grep  rsync
    
    # 注意:因为在服务端配置灵活性差,且维护麻烦,所以一般不在服务端进行排除的配置

    2.5 无差异同步

    1)--delete选项(实现无差异同步)

    • 要实现无差异同步,只需在服务端加上--delete参数即可实现
    • 使用--delete选项后,接收端的rsync会先删除目标目录下已经存在,但源端目录不存在的文件(多则删除,少则补充)

    2)无差异同步的风险

    • rsync推送:备份
      • --delete风险:本地有什么,远端就有什么,本地没有的,远端也要删除,服务端的目录数据可能丢失
    • rsync拉取:代码发布、下载
      • --delete风险:远端有什么,本地(客户端)就有什么,远端没有的,本地也要删除,本地的目录数据可能丢失

    3)无差异同步的应用场景

    一般是需要两台服务器之间,必须要求数据一致,且实时性又不是很高的情况;如两台负载均衡下面web服务器之间的同步,或者高可用双机配置之间的同步等。

    rsync无差异同步非常的危险,而且,有很多的替代方案,因此,生产场景如果没有特殊的需求,应该尽量避免使用。

    2.6 rsync服务共享多个目录的配置

    • 思路:将多个模块中共有的内容统一放到全局配置,然后在每个模块中写其特有的功能效果
    • 在多目录的共享中要注意用户对该共享目录的权限
    uid = rsync
    gid = rsync
    use  chroot = no
    max  connections = 200
    timeout = 300
    pid   file  =  /var/run/rsyncd.pid
    lock  file  =  /var/run/rsyncd.lock
    log   file  =  /var/log/rsync.log
    ignore errors 
    read only = false
    list = false
    hosts  allow  = 10.0.0.0/24
    hosts  deny  = 0.0.0.0/32
    auth  users = rsync_backup
    secrets  file  =  /etc/rsync.password
    [hgzero] path
    = /hgzero/ [data] path = /data/

    3. rsync实战案例

    3.1 rsync备份脚本

    #!/bin/sh
    ip=$(ifconfig ens33 | awk 'NR==2{print $2}')    # 获取本机ip地址
    
    [ ! -d /backup/$ip ] && mkdir -p /backup/$ip    # 判断是否有备份文件集中的目录,如果没有则创建
    
    cd  /backup/$ip   &&                           # 进入这个目录后对要备份的文件进行打包
        tar -zcf bak_$(date +%F).tar.gz  /var/www/html  /app/logs/access_$(date +%F -d -1day).log  /server/scripts/  /var/spool/cron 
        
    # 利用rsync将这些打包好的文件传送到备份服务器上    
    rsync -az /backup/  rsync_backup@10.0.0.101::backup/  --password-file=/etc/rsync.password  
        
    # 删除备份集中目录中7天以前的文件                                                                                        
    find  /backup  -type  f -name  "*.tar.gz"  -mtime  +7 | xargs  rm  -f   
    • 然后将以上脚本保存到 /server/script 中,添加到定时任务中就ok了
    • 如果是100台服务器需要备份,则将这100台服务器都作为rsync的客户端就ok了,定时执行以上脚本

    3.2 备份结果信息通知

    1)问题及解决思路

    • 问题:在备份数据后,需要把备份的成功以及失败的结果信息发送到系统管理员的邮箱中
    • 思路:需要在服务器端检查,而不是客户端直接将信息发送给管理员

    2)实现方式

    1. 先查看backup目录的大小,并写入记录,然后进行对比大写和修改时间来判断成功或失败
    2. 然后对文件进行打包、推送,再推送一个flag(ip+时间的文件名),本地清理7天以前的
      • 加上一个flag标记在以上执行脚本bak.sh中rsync语句的后面
        rsync -az /backup/ rsync_backup@10.0.0.101::backup/ --password-file=/etc/rsync.password && touch ${ip}_flag_$(date +%F) 
        # 表示如果rsync推送成功,就在本地创建一个flag文件来做标记
        # 但是这个标记文件并没有在rsync推送的时候一起推送过去,因为它的执行是在rsync之后,所以还需要来一次rsync推送来把这个标记文件也推送过去
        # 这时,如果在服务端看到这个标记文件,并且日期也对,则表示推送成功
        # 这是一种检查的思想
    3. 手工或定时的解包,模拟数据恢复来确定数据备份的完整性

    3.3 全网数据备份解决方案

    • 先做好数据同步rsync服务(备份服务器上部署rsync服务)
    • 本地打包备份脚本实现(webserver以及其他需要备份的机器上)
    • 配置定时任务执行脚本
    • 整体测试成功

    3.4 配置实时数据同步架构

    • 做好数据同步rsync服务(backup server上部署rsync服务)
    • 配置inotify服务,或者配置sersync服务(在客户端web服务器上配置)
    • 开发同步脚本,测试检查同步情况
    • 压力测试,查看并发是多少可以实时同步
    • 后台运行同步脚本,并且设置开机自启动(放入rc.local中)

    4. inotify详解

    4.1 inotify概述

    • 在客户端将rsync加入定时任务,可以实现定时同步数据,但是定时任务的同步时间粒度不能达到实时同步的要求,进而引入inotify
    • inotify是一种异步的文件系统事件监控机制软件,inotify是建立在rsync服务基础上进行配置的
    • 客户端通过inotify进行获取到目录内的变化,然后通知执行rsync命令同步数据
    • inotify的实现软件:inotify、sersync、lsyncd

    4.2 inotify的安装

    1)检查rsync服务是否正常运行,且是否可以进行数据的推送或拉取

    [root@c7_node_04 hg]# ps -ef |grep rsync
    root      19698      1  0 15:50 ?        00:00:00 rsync --daemon

    2)检查系统内核版本及文件检查

    [root@c7_node_05 rsync_test]# ll /proc/sys/fs/inotify/
    total 0
    -rw-r--r-- 1 root root 0 Sep 17 17:02 max_queued_events
    -rw-r--r-- 1 root root 0 Sep 17 17:02 max_user_instances
    -rw-r--r-- 1 root root 0 Sep 17 17:02 max_user_watches
    • 必须要有以下的这三个文件才可以继续以下操作
      • max_queued_events 表示最大的监控队列 , 这个值最好要调大一点(一般设置30万左右)
      • max_user_instances  表示用户的实例
      • max_user_watches  生产环境一般设置成5千万

    3)编译安装inotify工具

    • 先要安装好编译环境(如gcc编译工具等)
    tar xf inotify-tools-3.14.tar.gz
    ./configure --prefix=/usr/local/inotify-tools-3.14
    make && make install
    ln -s /usr/local/inotify-tools-3.14 /usr/local/inotify

    4)inotify的安装位置说明

    • inotify是监控工具,监控目录或文件的变化,然后触发一系列的操作。
    • 假如有一台站点发布服务器A,还有3台web服务器B/C/D,目的是让服务器A上存放站点的目录中有文件变化时,自动触发同步将它们推到web服务器上,这样能够让web服务器最快的获取到最新的文件。
    • 监控的是A上的目录,推送到的是B/C/D服务器,所以在站点发布服务器A上装好inotify工具
    • 一般还在web服务器BCD上将rsync配置为daemon运行模式,让其在873端口上处于监听状态(并非必须,即使是sersync也非必须如此)。
    • 对于rsync来说,监控端是rsync的客户端,其他的是rsync的服务端,但并非一定需要如此
    • inotify是独立的工具,它和rsync无关,它只是为rsync提供一种比较好的实时同步方式而已。

    4.3 inotify-tools使用说明

    1)inotify-tools软件结构

    • /usr/bin/inotifywait
      • 实时监控文件目录的实时事件,等待文件发生变化
    • /usr/bin/inotifywatch
      • 用于统计文件系统的事件

    2)inotifywait使用参数(实时监控文件目录中的所有事件)

    -r ,--recursive       # 递归查询目录
    -q ,--quite           # 打印很少的信息,仅打印事件信息
    -m ,--monitor         # 始终保持事件监听状态,否则应该是监控到了一次就退出监控了
    --exclude  <pattern>   # 通过模式匹配来指定不被监控的文件,区分大小写
    --excludei <pattern>   # 通过模式匹配来指定不被监控的文件,并不区分大小写
    --timefmt              # 指定时间输出的格式
    --format               # 打印使用指定的输出类似格式字符串,如[--format '%w%f %e%T']
        %w:产生事件的监控路径,不一定就是发生事件的具体文件,例如递归监控一个目录,该目录下的某文件产生事件,将输出该目录而非其内具体的文件
        %f:如果监控的是一个目录,则输出产生事件的具体文件名。其他所有情况都输出空字符串
        %e:产生的事件名称
        %T:以"--timefmt"定义的时间格式输出当前时间,要求同时定义"--timefmt"
        
    -e   # 通过此参数可以指定需要监控的事件:
                access       文件或目录被读取
                modify       文件或目录被修改
                attrib       元数据被修改,包括权限、时间戳、扩展属性等
                close        文件或目录封闭,无论读还是写模式
                close_write  文件或目录在写入模式之后被关闭
    close_nowrite只读模式下文件被关闭,即只能是为了读取而打开文件,读取结束后关闭文件的事件 open 文件或目录被打开 moved_to 文件或目录被移动至另外一个目录
    moved_from 将监控目录下文件或目录移动到其他地方,也可以是在监控目录内部的移动 move 文件或目录被移动到另一个目录或从另一个目录移动到当前目录,是moved_to和moved_from的结合 create 文件或目录被创建在当前目录 delete 文件或目录被删除 umount 挂载在被监控目录上的文件系统被umount,umount后不再监控此目录
    isdir 监控目录相关操作

    4.4 inotify监听实例

    /usr/local/inotify-tools-3.14/bin/inotifywait  -mrq --timefmt '%d/%m/%y %H:%M'  --format '%T %w%f' -e create /data
    # 当/data/目录中有新的内容被创建时,就会产生反馈(以指定的样式来打印时间和文件名)
    
    /usr/local/inotify-tools-3.14/bin/inotifywait  -mrq --timefmt '%d/%m/%y %H:%M'  --format '%T %w%f' -e create,delete  /data
    # 当/data/目录中有内容被创建和删除时,就会产生反馈
    • inotify进行实时同步生产环境中的最大文件数量是200到300个,大小是10到500k,若超过这个数字就会有延迟

    4.5 rsync+inotify实时同步脚本

    1)rsync+inotify的简单实现

    #!/bin/sh
    cmd="/usr/local/inotify/bin/inotifywait"
    $cmd  -mrq  --format  '%w%f'  -e  create,close_write,delete  /backup|
    while read line
    do
        [!  -e  "$line" ] &&  continue
        rsync  -az  --delete  $line  rsync_backup@10.0.0.2::hgzero  --password-file=/etc/rsync.password
    done

    2)rsync+inotify的最佳实现

    #!/bin/bash 
    watch_dir=/www
    push_to=172.16.10.5
     
    # First to do is initial sync
    rsync -az --delete --exclude="*.swp" --exclude="*.swx" $watch_dir $push_to:/tmp
     
    inotifywait -mrq -e delete,close_write,moved_to,moved_from,isdir --timefmt '%Y-%m-%d %H:%M:%S' --format '%w%f:%e:%T' $watch_dir 
    --exclude=".*.swp" >>/etc/inotifywait.log &
     
    while true;do
         if [ -s "/etc/inotifywait.log" ];then
            grep -i -E "delete|moved_from" /etc/inotifywait.log >> /etc/inotify_away.log
            rsync -az --delete --exclude="*.swp" --exclude="*.swx" $watch_dir $push_to:/tmp
            if [ $? -ne 0 ];then
               echo "$watch_dir sync to $push_to failed at `date +"%F %T"`,please check it by manual" |
               mail -s "inotify+Rsync error has occurred" root@localhost
            fi
            cat /dev/null > /etc/inotifywait.log
            rsync -az --delete --exclude="*.swp" --exclude="*.swx" $watch_dir $push_to:/tmp
        else
            sleep 1
        fi
    done
  • 相关阅读:
    进程虚拟内存
    非连续内存区缺页异常处理
    请求调页和写时复制
    标签对齐(补充)
    shell数学表达式
    缺页异常的处理
    不错的书籍
    imag database2
    image database
    Apache down了?
  • 原文地址:https://www.cnblogs.com/hgzero/p/13684442.html
Copyright © 2011-2022 走看看