成航先森 成航先森

成都航院计算机系一个学生的个人博客

 

随便看看:

分段图 CDNkeepalivedLinuxmysqlnginxrsyncUEditorWordPressWordPress插件七牛体育部信息志愿服务队免流全体例会向党组织靠拢团学会学习部宣传部影视相关心理部成都航院报社招生信息教学资源文艺部毕业就业流量活动生活杂谈社会实践部站长经历系部介绍系部动态纪检部组织部经验分享老师腾讯云资源下载轻松时刻高考录取分数线

标签:rsync

CentOS搭建lsyncd实时同步——取代rsync+inotify

经验杂笔CentOS搭建lsyncd实时同步——取代rsync+inotify

标签:, | 3 条评论 | 2018-02-08

昨天先森发布了“CentOS下inotify+rsync实现文件实时同步”,inotify+rsync实时同步的方案是用shell在后台常驻来实现实时同步,没有守护进程,感觉不是很靠谱,如果脚本突然挂了,实时同步岂不是GG了?所以先森在实现了inotify+rsync后还是再找其他的解决方案。其实在找到lsyncd之前,先森先找到了sersync这个工具,但是好像这个工具很久没有更新了,所以虽然也有较多好评,但是先森目前还是先研究lsyncd了。当然,无论是sersync还是lsyncd,其实都是对inotify这个内核中的文件事件监控系统进行了封装,类似inotify-tools,给我们提供的是封装好了的inotify+rsync工具。sersync是用C写的,lsyncd是使用lua语言封装的。搭建lsyncd实时同步lsyncdlsyncd项目也托管在GitHub上面,具体地址是https://github.com/axkibe/lsyncd,一会儿若是要编译安装也需要去这个地方。上文也说过,lsyncd是使用lua语言封装的,所以初识lsyncd的配置文件时,还是有点不习惯,但是用久应该就还好了。lsyncd不仅仅是实现两台服务器的同步的,它还能够在一台服务器内对两个文件夹进行同步,这里可以是cp,也可以是rsync。两台或多台服务器间可以是rsync,也可以是rsyncssh。本文主要讲的是两台服务器间的rsync。lsyncd可以配置inotify检测到文件变动后多少秒才执行同步,也就是时间延迟。也可以配置文件变动个数达到多少个后立即执行同步,无论有没有到达前面的时间延迟的要求,这就是累计触发事件次数。这两个配置可以减少rsync的同步,避免海量文件同步时rsync的频繁发送文件对比列表。lsyncd安装lsyncd的安装方式有两种,yum安装和编译安装。yum安装:yum安装也有两种方式,一个是阿里云的镜像源,一个是fedoraproject的镜像源。阿里云:#CentOS 7wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo#CentOS 6wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo#yum 安装yum install lsyncd -yfedoraproject:#只找到CentOS 6的rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpmyum install lsyncd -y编译安装:1、首先还是去上文提到的GitHub上下载项目,通过下面的下载就是最新的了:wget https://github.com/axkibe/lsyncd/archive/master.zip2、下载了软件包,先别急着安装,上文提到了几次,lsyncd是用lua语言封装的,所以还需要安装lua环境。另外lsyncd不是使用的make,而是cmake,所以也需要安装cmake。yum install -y lua lua-devel asciidoc cmake3、下载了软件包,装好了环境依赖,下面就是编译安装:unzip lsyncd-master.zipcd lsyncd-mastercmake -DCMAKE_INSTALL_PREFIX=/usr/local/lsyncdmake && make install安装好了的lsyncd在/usr/local/lsyncd下。配置文件、日志文件夹等需要我们自己定义与创建。4、配置文件。先森的配置文件是用于两台服务器间实时同步的,使用的是rsync模式。lsyncd的配置文件其实有点类似nginx,如nginx的server可以多定义互不冲突一样,lsyncd也可以多个定义。settings {    logfile ="/usr/local/lsyncd/logs/lsyncd.log",    statusFile ="/usr/local/lsyncd/logs/lsyncd.status",    inotifyMode = "CloseWrite or Modify",    maxProcesses = 15,    }sync {    default.rsync,    source    = "/web/data/ftp",    target    = "user@172.17.8.16::datahome",    delete="running",    exclude = { ".*", ".tmp","*.swp","*.swx" },    delay = 0,    rsync     = {        binary = "/usr/bin/rsync",        archive = true,        compress = true,        verbose   = true,        password_file = "/etc/rsyncd/rsync.passwd",        }    }注释版:settings {    --定义日志文件    logfile ="/usr/local/lsyncd/logs/lsyncd.log",    --定义状态文件    statusFile ="/usr/local/lsyncd/logs/lsyncd.status",    --指定inotify监控的事件,默认是CloseWrite,还可以是Modify或CloseWrite or Modify    --这个就是使用的inotify能监控的事件    inotifyMode = "CloseWrite or Modify",    --同步进程的最大个数。假如同时有20个文件需要同步,而maxProcesses = 8,则最大能看到有8个rysnc进程    maxProcesses = 15,    --(这个配置先森没有使用)累计到多少所监控的事件激活一次同步,即使后面的delay延迟时间还未到。    --maxDelays=10,    }sync {    --使用rsync通过daemon方式连接远程rsyncd进程;    default.rsync,    --同步的源目录,使用绝对路径。    source    = "/web/data/ftp",    --定义目的地址,对应不同的模式有不同的写法。这里是远程rsync,使用“用户名@ip::模块名”写法。    target    = "user@172.17.8.16::datahome",    --是否同步删除,除了running选项,还有true、false和startup,这个配置先森不是很明白,大概是true是完全同步删除,false是不允许删除,startup和running要难理解一些\    --先森的理解是,startup是仅在启动时将源目录和目的目录来一次完全同步,lsyncd运行时的源目录的删除文件在目的目录中不做删除操作\    --running是启动时不对源、目的目录进行完全同步,lsyncd运行时源目录删除的文件,目的目录也会被删除。    delete="running",    --排除的文件,这里排除了一些隐藏文件,和文件打开是时的临时文件    exclude = { ".*", ".tmp","*.swp","*.swx" },    -- 累计事件,等待rsync同步延时时间,默认15秒。先森配置的是0,也就是实时同步。    delay = 0,    rsync     = {        --本地rsync命令路径        binary = "/usr/bin/rsync",        archive = true,        compress = true,        verbose   = true,        --远程rsyncd的密码        password_file = "/etc/rsyncd/rsync.passwd",        }    }5、启动lsyncd/usr/local/lsyncd/bin/lsyncd -log Exec /usr/local/lsyncd/lsyncd.conf也可以自己创建一个启动脚本,脚本内容如下,是先森从yum安装的lsyncd拷贝的,一样的可以使用。只是用之前,需要对lsyncd守护命令与配置文件先做个软连接,免得需要修改启动脚本:ln -s /usr/local/lsyncd/bin/lsyncd /usr/bin/lsyncdln -s /usr/local/lsyncd/lsyncd.conf /etc/lsyncd.conf启动脚本:#!/bin/bash## chkconfig: - 85 15# description: Lightweight inotify based sync daemon## processname:  lsyncd# config:       /etc/lsyncd.conf# config:       /etc/sysconfig/lsyncd# pidfile:      /var/run/lsyncd.pid# Source function library. /etc/init.d/functions# Source networking configuration.. /etc/sysconfig/network# Check that networking is up.[ "$NETWORKING" = "no" ] && exit 0LSYNCD_OPTIONS="-pidfile /var/run/lsyncd.pid /etc/lsyncd.conf"if [ -e /etc/sysconfig/lsyncd ]; then  . /etc/sysconfig/lsyncdfiRETVAL=0prog="lsyncd"thelock=/var/lock/subsys/lsyncdstart() { [ -f /etc/lsyncd.conf ] || exit 6        echo -n $"Starting $prog: "        if [ $UID -ne 0 ]; then                RETVAL=1                failure        else                daemon ${LSYNCD_USER:+--user ${LSYNCD_USER}} /usr/bin/lsyncd $LSYNCD_OPTIONS                RETVAL=$?                [ $RETVAL -eq 0 ] && touch $thelock        fi;        echo        return $RETVAL}stop() {        echo -n $"Stopping $prog: "        if [ $UID -ne 0 ]; then                RETVAL=1                failure        else                killproc lsyncd                RETVAL=$?                [ $RETVAL -eq 0 ] && rm -f $thelock        fi;        echo        return $RETVAL}reload(){        echo -n $"Reloading $prog: "        killproc lsyncd -HUP        RETVAL=$?        echo        return $RETVAL}restart(){        stop        start}condrestart(){    [ -e $thelock ] && restart    return 0}case "$1" in  start)        start        ;;  stop)        stop        ;;  restart)        restart        ;;  reload)        reload        ;;  condrestart)        condrestart        ;;  status)        status lsyncd        RETVAL=$?        ;;  *)        echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"        RETVAL=1esacexit $RETVAL优化因为lsyncd其实也是用到了inotify,所以和inotify+rsync方案一样,我们还是需要对服务器的inotify内核配置进行优化。inotify检查磁盘变动是有队列等值的配置的,inotify默认内核参数值太小,会导致实际检测的时候报错。查看系统默认参数值sysctl -a | grep max_queued_eventssysctl -a | grep max_user_watchessysctl -a | grep max_user_instances临时修改sysctl -w fs.inotify.max_queued_events="99999999"sysctl -w fs.inotify.max_user_watches="99999999"sysctl -w fs.inotify.max_user_instances="65535"固定修改:vim /etc/sysctl.conf #添加以下代码fs.inotify.max_queued_events=99999999fs.inotify.max_user_watches=99999999fs.inotify.max_user_instances=65535其他官方配置文件wiki:https://axkibe.github.io/lsyncd/manual/config/file/

CentOS下inotify+rsync实现文件实时同步

经验杂笔CentOS下inotify+rsync实现文件实时同步

标签:, | 0条评论 | 2018-02-07

rsync仅同步差异文件,所以传输效率较高,所以先森在项目中负载的资源服务器做了rsync同步,确保通过负载IP都能访问到相同的文件,使用crontab计划任务每1分钟执行一次同步。计划任务最小时间刻度为1分钟(虽然可以用数学方法再调小,但是运行密度大了对服务器会造成负荷),也就是上传一张图片,最长可能要等1分钟后才能在其它服务器上访问,如果同步目录下的文件基数是百万级的,那么时间可能更久。这种方案先森曾发过:CentOS下rsync服务器安装与配置-数据同步|文件增量备份inotify+rsync实时同步rsync的不足rsync具有安全性高、备份迅速、支持增量备份等优点,通过rsync可以解决实时性不高的数据备份需求,例如定期数据库备份。但随着业务规模的扩大,业务需求的增加,rsync的缺点也暴露出来了:1、当文件数量大到百万级别,rsync仅差异扫描就是一项非常耗时的工作;2、rsync自身不能实时的检测并同步数据,它总是被动的通过各种方式去触发同步。inotify与inotify-tools注:inotify是一个 Linux 内核特性,inotify-tools是为linux下inotify文件监控工具提供的一套C的开发接口库函数。inotify:inotify是一种强大的、细粒度的、异步的文件系统事件监控机制,Linux内核从2.6.13开始引入,允许监控程序打开一个独立文件描述符,并针对事件集监控一个或者多个文件,例如打开、关闭、移动/重命名、删除、创建或者改变属性。CentOS 6是已经支持的了,判断服务器是否支持inotify,只需要执行下面命令,查看是否有结果即可。ll /proc/sys/fs/inotifyinotify-tools:inotify-tools是为linux下inotify文件监控工具提供的一套C的开发接口库函数,同时还提供了一系列的命令行工具,这些工具可以用来监控文件系统的事件。inotify-tools是用c编写的,除了要求内核支持inotify外,不依赖于其他。inotify-tools提供两种工具,一是inotifywait,它是用来监控文件或目录的变化,二是inotifywatch,它是用来统计文件系统访问的次数。我们主要用到的是inotifywait工具。inotify-tools安装inotify-tools先森找到了两种安装方式,rpm安装和编译安装,先森用的是编译安装。rpm安装wget http://dl.fedoraproject.org/pub/epel/6/x86_64/Packages/i/inotify-tools-3.14-1.el6.x86_64.rpmrpm -vhi inotify-tools-3.14-1.el6.x86_64.rpm编译安装编译前请确保服务器已安装编译组件:yum install -y make  gcc gcc-c++这个项目是发布在github上的,下载也是在github上下载。但是先森在项目首页下载下来的无法编译安装,所以安装的还是3.1.4版本的。github项目地址:https://github.com/rvoicilas/inotify-tools/编译安装:wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gztar zxvf inotify-tools-3.14.tar.gzcd inotify-tools-3.14./configure    #或./configure --prefix=/usr/local/inotifymakemake install安装后命令在/usr/local/bin/目录下。查看效果:/usr/local/bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib /data/不停止上面的命令,新建终端连接然后进入/data/文件夹进行各类操作,可以看下上面输出的结果。rsync组合inotify-tools完成实时同步inotify的作用,是让我们知道监控的文件夹中有变动,我们可以根据inotify输出内容,去触发rsync同步。提示:以往使用crontab触发rsync时,我们是将rsync服务端搭建在主服务器,其他服务器去主服务器同步文件。而inotify+rsync的方式,是将rsync服务端搭建在从服务器,主服务器推送文件到从服务器,所以从服务器上的rsync配置中“read only”要配置为no,也就是“read only = no”。inotify-tools只是个工具,并不是软件,所以要与rsync配合就需要我们自己写shell脚本,并让脚本一直运行在后台。先森通过实际测试,整理出了两个脚本,也就是两种方案。方案1:#!/bin/bashsource /etc/profilesrc=/data/                           # 需要同步的源路径des=datahome                             # 目标服务器上 rsync 模块名rsync_passwd_file=/etc/rsyncd/rsync.passwd            # rsync验证的密码文件ipaddr=(10.0.0.1)                 # 目标服务器,多个目标服务器以空格分开user=user                            # rsync --daemon定义的验证用户名logs=/var/log/inotify_rsync.logs     # 日志inotify_rsync(){cd ${src}                              # 此方法中,由于rsync同步的特性,这里必须要先cd到源目录,inotify再监听 ./ 才能rsync同步后目录结构一致,有兴趣的同学可以进行各种尝试观看其效果/usr/local/bin/inotifywait -mrq --format  '%Xe %w%f' -e modify,create,delete,attrib,close_write,move --exclude=".*.swp" ./ | 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' ]]         # 判断事件类型        then                echo 'CREATE or MODIFY or CLOSE_WRITE or MOVED_TO' for ip in ${ipaddr[@]} do                    rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx"  $(dirname ${INO_FILE}) ${user}@${ip}::${des} >> $logs        # INO_FILE变量代表路径哦  -c校验文件内容 done                 #仔细看 上面的rsync同步命令 源是用了$(dirname ${INO_FILE})变量 即每次只针对性的同步发生改变的文件的目录(只同步目标文件的方法在生产环境的某些极端环境下会漏文件 现在可以在不漏文件下也有不错的速度 做到平衡) 然后用-R参数把源的目录结构递归到目标后面 保证目录结构一致性        fi        #删除、移动出事件        if [[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]]        then                echo 'DELETE or MOVED_FROM'                echo 'CREATE or MODIFY or CLOSE_WRITE or MOVED_TO'                for ip in ${ipaddr[@]}                do                    rsync -avzR --delete --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx"  $(dirname ${INO_FILE}) ${user}@${ip}::${des} >> $logs  done                #看rsync命令 如果直接同步已删除的路径${INO_FILE}会报no such or directory错误 所以这里同步的源是被删文件或目录的上一级路径,并加上--delete来删除目标上有而源中没有的文件,这里不能做到指定文件删除,如果删除的路径越靠近根,则同步的目录月多,同步删除的操作就越花时间。这里有更好方法的同学,欢迎交流。        fi        #修改属性事件 指 touch chgrp chmod chown等操作        if [[ $INO_EVENT =~ 'ATTRIB' ]]        then                echo 'ATTRIB'                if [ ! -d "$INO_FILE" ]                 # 如果修改属性的是目录 则不同步,因为同步目录会发生递归扫描,等此目录下的文件发生同步时,rsync会顺带更新此目录。                then                for ip in ${ipaddr[@]}                do                        rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx"  $(dirname ${INO_FILE}) ${user}@${ip}::${des} >> $logs  done                fi        fidoneinotify_rsync >> $logs 2>&1}inotify_rsync >> $logs 2>&1将上面内容保存为inotify_rsync_A.sh,执行:inotify_rsync_A.sh &或使用screen后台启动。另外,为避免意外遗漏文件,最好在定时任务中每隔两个小时执行一次全目录同步。这个方案的优点:利用inotify让rsync每次仅同步有更改的文件,减少递归操作。缺点:经过先森实际运用发现,inotify的特性,每次创建文件会产生多条输出,而这个脚本inotify的每条输出都会触发一次rsync,这样会对服务器资源产生浪费。方案2:为了解决方案1的问题,先森找到了另一个脚本,对方案1的脚本进行了修改:#!/bin/bashsource /etc/profilesrc=/data/                           # 需要同步的源路径des=datahome                             # 目标服务器上 rsync 模块名rsync_passwd_file=/etc/rsyncd/rsync.passwd            # rsync验证的密码文件ipaddr=(10.0.0.1)                 # 目标服务器,多个目标服务器以空格分开user=user                            # rsync --daemon定义的验证用户名inlogs=/var/log/inotifywait.logslogs=/var/log/inotify_rsync.logserrlog=/var/log/inotify_rsync.err.logscd ${src}                              # 此方法中,由于rsync同步的特性,这里必须要先cd到源目录,inotify再监听 ./ 才能rsync同步后目录结构一致,有兴趣的同学可以进行各种尝试观看其效果/usr/local/bin/inotifywait -mrq --format  '%Xe %w%f' -e modify,create,delete,attrib,close_write,move --exclude=".*.swp" ./ >> $inlogs &while true;do     if [ -s ${inlogs} ];then        grep -i -E "delete|moved_from" ${inlogs} >> /var/log/inotify_away.log for ip in ${ipaddr[@]} do rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx" ${src} ${user}@${ip}::${des} >> $logs RETVAL=$? done #同步失败后的输出日志        if [ $RETVAL -ne 0 ];then           echo "${src} sync to ${ipaddr} failed at `date +"%F %T"`,please check it by manual" >> $errlog        fi        cat /dev/null > $inlogs for ip in ${ipaddr[@]} do rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx" ${src} ${user}@${ip}::${des} >> $logs done    else        sleep 1    fidone这个脚本是将inotify的检测内容输出到文件/var/log/inotifywait.logs,脚本判断这个文件是否为空,非空则表明有变动,那么就来一次完整的同步。如果文件为空则睡眠1秒。将上面内容保存为inotify_rsync_B.sh,执行:inotify_rsync_B.sh &这个方案的优点:不会根据inotify输出重复触发rsync同步。缺点:每次都是rsync完整同步,如果文件数量较大则对比时间会比较长。inotify优化inotify检查磁盘变动是有队列等值的配置的,inotify默认内核参数值太小,会导致实际检测的时候报错。查看系统默认参数值sysctl -a | grep max_queued_eventssysctl -a | grep max_user_watchessysctl -a | grep max_user_instances临时修改sysctl -w fs.inotify.max_queued_events="99999999"sysctl -w fs.inotify.max_user_watches="99999999"sysctl -w fs.inotify.max_user_instances="65535"固定修改:vim /etc/sysctl.conf #添加以下代码fs.inotify.max_queued_events=99999999fs.inotify.max_user_watches=99999999fs.inotify.max_user_instances=65535

官方微信
返回顶部