CentOS下inotify+rsync實(shí)現(xiàn)文件實(shí)時(shí)同步
編輯:狂族晨曦 來(lái)源:腳本編程,系統(tǒng)運(yùn)維,經(jīng)驗(yàn)雜筆 日期:2018-02-07 閱讀: 4,053 次 搶個(gè)沙發(fā) 百度已收錄
rsync僅同步差異文件,所以傳輸效率較高,所以先森在項(xiàng)目中負(fù)載的資源服務(wù)器做了rsync同步,確保通過(guò)負(fù)載IP都能訪問(wèn)到相同的文件,使用crontab計(jì)劃任務(wù)每1分鐘執(zhí)行一次同步。
計(jì)劃任務(wù)最小時(shí)間刻度為1分鐘(雖然可以用數(shù)學(xué)方法再調(diào)小,但是運(yùn)行密度大了對(duì)服務(wù)器會(huì)造成負(fù)荷),也就是上傳一張圖片,最長(zhǎng)可能要等1分鐘后才能在其它服務(wù)器上訪問(wèn),如果同步目錄下的文件基數(shù)是百萬(wàn)級(jí)的,那么時(shí)間可能更久。
這種方案先森曾發(fā)過(guò):CentOS下rsync服務(wù)器安裝與配置-數(shù)據(jù)同步|文件增量備份

inotify+rsync實(shí)時(shí)同步
rsync的不足
rsync具有安全性高、備份迅速、支持增量備份等優(yōu)點(diǎn),通過(guò)rsync可以解決實(shí)時(shí)性不高的數(shù)據(jù)備份需求,例如定期數(shù)據(jù)庫(kù)備份。
但隨著業(yè)務(wù)規(guī)模的擴(kuò)大,業(yè)務(wù)需求的增加,rsync的缺點(diǎn)也暴露出來(lái)了:
1、當(dāng)文件數(shù)量大到百萬(wàn)級(jí)別,rsync僅差異掃描就是一項(xiàng)非常耗時(shí)的工作;
2、rsync自身不能實(shí)時(shí)的檢測(cè)并同步數(shù)據(jù),它總是被動(dòng)的通過(guò)各種方式去觸發(fā)同步。
inotify與inotify-tools
注:inotify是一個(gè) Linux 內(nèi)核特性,inotify-tools是為linux下inotify文件監(jiān)控工具提供的一套C的開(kāi)發(fā)接口庫(kù)函數(shù)。
inotify:
inotify是一種強(qiáng)大的、細(xì)粒度的、異步的文件系統(tǒng)事件監(jiān)控機(jī)制,Linux內(nèi)核從2.6.13開(kāi)始引入,允許監(jiān)控程序打開(kāi)一個(gè)獨(dú)立文件描述符,并針對(duì)事件集監(jiān)控一個(gè)或者多個(gè)文件,例如打開(kāi)、關(guān)閉、移動(dòng)/重命名、刪除、創(chuàng)建或者改變屬性。
CentOS 6是已經(jīng)支持的了,判斷服務(wù)器是否支持inotify,只需要執(zhí)行下面命令,查看是否有結(jié)果即可。
ll /proc/sys/fs/inotify
inotify-tools:
inotify-tools是為linux下inotify文件監(jiān)控工具提供的一套C的開(kāi)發(fā)接口庫(kù)函數(shù),同時(shí)還提供了一系列的命令行工具,這些工具可以用來(lái)監(jiān)控文件系統(tǒng)的事件。
inotify-tools是用c編寫(xiě)的,除了要求內(nèi)核支持inotify外,不依賴于其他。
inotify-tools提供兩種工具,一是inotifywait,它是用來(lái)監(jiān)控文件或目錄的變化,二是inotifywatch,它是用來(lái)統(tǒng)計(jì)文件系統(tǒng)訪問(wèn)的次數(shù)。我們主要用到的是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.rpm rpm -vhi inotify-tools-3.14-1.el6.x86_64.rpm
編譯安裝
編譯前請(qǐng)確保服務(wù)器已安裝編譯組件:
yum install -y make gcc gcc-c++
這個(gè)項(xiàng)目是發(fā)布在github上的,下載也是在github上下載。但是先森在項(xiàng)目首頁(yè)下載下來(lái)的無(wú)法編譯安裝,所以安裝的還是3.1.4版本的。
github項(xiàng)目地址:https://github.com/rvoicilas/inotify-tools/
編譯安裝:
wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz tar zxvf inotify-tools-3.14.tar.gz cd inotify-tools-3.14 ./configure #或./configure --prefix=/usr/local/inotify make make install
安裝后命令在/usr/local/bin/目錄下。
查看效果:
/usr/local/bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib /data/
不停止上面的命令,新建終端連接然后進(jìn)入/data/文件夾進(jìn)行各類操作,可以看下上面輸出的結(jié)果。
rsync組合inotify-tools完成實(shí)時(shí)同步
inotify的作用,是讓我們知道監(jiān)控的文件夾中有變動(dòng),我們可以根據(jù)inotify輸出內(nèi)容,去觸發(fā)rsync同步。
提示:以往使用crontab觸發(fā)rsync時(shí),我們是將rsync服務(wù)端搭建在主服務(wù)器,其他服務(wù)器去主服務(wù)器同步文件。而inotify+rsync的方式,是將rsync服務(wù)端搭建在從服務(wù)器,主服務(wù)器推送文件到從服務(wù)器,所以從服務(wù)器上的rsync配置中“read only”要配置為no,也就是“read only = no”。
inotify-tools只是個(gè)工具,并不是軟件,所以要與rsync配合就需要我們自己寫(xiě)shell腳本,并讓腳本一直運(yùn)行在后臺(tái)。
先森通過(guò)實(shí)際測(cè)試,整理出了兩個(gè)腳本,也就是兩種方案。
方案1:
#!/bin/bash
source /etc/profile
src=/data/ # 需要同步的源路徑
des=datahome # 目標(biāo)服務(wù)器上 rsync 模塊名
rsync_passwd_file=/etc/rsyncd/rsync.passwd # rsync驗(yàn)證的密碼文件
ipaddr=(10.0.0.1) # 目標(biāo)服務(wù)器,多個(gè)目標(biāo)服務(wù)器以空格分開(kāi)
user=user # rsync --daemon定義的驗(yàn)證用戶名
logs=/var/log/inotify_rsync.logs # 日志
inotify_rsync(){
cd ${src} # 此方法中,由于rsync同步的特性,這里必須要先cd到源目錄,inotify再監(jiān)聽(tīng) ./ 才能rsync同步后目錄結(jié)構(gòu)一致,有興趣的同學(xué)可以進(jìn)行各種嘗試觀看其效果
/usr/local/bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib,close_write,move --exclude=".*.swp" ./ | while read file # 把監(jiān)控到有發(fā)生更改的"文件路徑列表"循環(huán)
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
#增加、修改、寫(xiě)入完成、移動(dòng)進(jìn)事件
#增、改放在同一個(gè)判斷,因?yàn)樗麄兌伎隙ㄊ轻槍?duì)文件的操作,即使是新建目錄,要同步的也只是一個(gè)空目錄,不會(huì)影響速度。
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校驗(yàn)文件內(nèi)容
done
#仔細(xì)看 上面的rsync同步命令 源是用了$(dirname ${INO_FILE})變量 即每次只針對(duì)性的同步發(fā)生改變的文件的目錄(只同步目標(biāo)文件的方法在生產(chǎn)環(huán)境的某些極端環(huán)境下會(huì)漏文件 現(xiàn)在可以在不漏文件下也有不錯(cuò)的速度 做到平衡) 然后用-R參數(shù)把源的目錄結(jié)構(gòu)遞歸到目標(biāo)后面 保證目錄結(jié)構(gòu)一致性
fi
#刪除、移動(dòng)出事件
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}會(huì)報(bào)no such or directory錯(cuò)誤 所以這里同步的源是被刪文件或目錄的上一級(jí)路徑,并加上--delete來(lái)刪除目標(biāo)上有而源中沒(méi)有的文件,這里不能做到指定文件刪除,如果刪除的路徑越靠近根,則同步的目錄月多,同步刪除的操作就越花時(shí)間。這里有更好方法的同學(xué),歡迎交流。
fi
#修改屬性事件 指 touch chgrp chmod chown等操作
if [[ $INO_EVENT =~ 'ATTRIB' ]]
then
echo 'ATTRIB'
if [ ! -d "$INO_FILE" ] # 如果修改屬性的是目錄 則不同步,因?yàn)橥侥夸洉?huì)發(fā)生遞歸掃描,等此目錄下的文件發(fā)生同步時(shí),rsync會(huì)順帶更新此目錄。
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
fi
done
inotify_rsync >> $logs 2>&1
}
inotify_rsync >> $logs 2>&1
將上面內(nèi)容保存為inotify_rsync_A.sh,執(zhí)行:
inotify_rsync_A.sh &
或使用screen后臺(tái)啟動(dòng)。
另外,為避免意外遺漏文件,最好在定時(shí)任務(wù)中每隔兩個(gè)小時(shí)執(zhí)行一次全目錄同步。
這個(gè)方案的優(yōu)點(diǎn):利用inotify讓rsync每次僅同步有更改的文件,減少遞歸操作。
缺點(diǎn):經(jīng)過(guò)先森實(shí)際運(yùn)用發(fā)現(xiàn),inotify的特性,每次創(chuàng)建文件會(huì)產(chǎn)生多條輸出,而這個(gè)腳本inotify的每條輸出都會(huì)觸發(fā)一次rsync,這樣會(huì)對(duì)服務(wù)器資源產(chǎn)生浪費(fèi)。
方案2:
為了解決方案1的問(wèn)題,先森找到了另一個(gè)腳本,對(duì)方案1的腳本進(jìn)行了修改:
#!/bin/bash
source /etc/profile
src=/data/ # 需要同步的源路徑
des=datahome # 目標(biāo)服務(wù)器上 rsync 模塊名
rsync_passwd_file=/etc/rsyncd/rsync.passwd # rsync驗(yàn)證的密碼文件
ipaddr=(10.0.0.1) # 目標(biāo)服務(wù)器,多個(gè)目標(biāo)服務(wù)器以空格分開(kāi)
user=user # rsync --daemon定義的驗(yàn)證用戶名
inlogs=/var/log/inotifywait.logs
logs=/var/log/inotify_rsync.logs
errlog=/var/log/inotify_rsync.err.logs
cd ${src} # 此方法中,由于rsync同步的特性,這里必須要先cd到源目錄,inotify再監(jiān)聽(tīng) ./ 才能rsync同步后目錄結(jié)構(gòu)一致,有興趣的同學(xué)可以進(jìn)行各種嘗試觀看其效果
/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
fi
done
這個(gè)腳本是將inotify的檢測(cè)內(nèi)容輸出到文件/var/log/inotifywait.logs,腳本判斷這個(gè)文件是否為空,非空則表明有變動(dòng),那么就來(lái)一次完整的同步。如果文件為空則睡眠1秒。
將上面內(nèi)容保存為inotify_rsync_B.sh,執(zhí)行:
inotify_rsync_B.sh &
這個(gè)方案的優(yōu)點(diǎn):不會(huì)根據(jù)inotify輸出重復(fù)觸發(fā)rsync同步。
缺點(diǎn):每次都是rsync完整同步,如果文件數(shù)量較大則對(duì)比時(shí)間會(huì)比較長(zhǎng)。
inotify優(yōu)化
inotify檢查磁盤變動(dòng)是有隊(duì)列等值的配置的,inotify默認(rèn)內(nèi)核參數(shù)值太小,會(huì)導(dǎo)致實(shí)際檢測(cè)的時(shí)候報(bào)錯(cuò)。
查看系統(tǒng)默認(rèn)參數(shù)值
sysctl -a | grep max_queued_events sysctl -a | grep max_user_watches sysctl -a | grep max_user_instances
臨時(shí)修改
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=99999999 fs.inotify.max_user_watches=99999999 fs.inotify.max_user_instances=65535
轉(zhuǎn)載請(qǐng)注明出處來(lái)自http://www.cnidcc.cn/inotify_rsync.html

川公網(wǎng)安備 51011202000104號(hào)