rsync推拉模型及结合inotify实现推模型自动同步
?
一、前言
無論使用什么操作系統(tǒng)下,都經(jīng)常有同步文件的需求,不管發(fā)生在本地,還是發(fā)生在本地和遠(yuǎn)程主機(jī)之間。那么應(yīng)該怎么做呢?
使用拷貝類的命令,本地使用cp命令,復(fù)制到遠(yuǎn)程主機(jī)使用scp這樣的命令,保證復(fù)制到目標(biāo)和源的一模一樣。
但是,這種復(fù)制一般來說,只能判斷文件在目標(biāo)中是否存在,然后對(duì)存在的文件或目錄可以選擇覆蓋或者不復(fù)制,覆蓋能保證文件一致,不復(fù)制就不能保證一致,不存在的則創(chuàng)建這個(gè)文件或者目錄。
每次同步如果都采用覆蓋,即使只是少數(shù)文件發(fā)生部分變化,也是全部文件都覆蓋,源和目標(biāo)倒是保證一致了。但這種方式,會(huì)造成極大的網(wǎng)絡(luò)帶寬壓力和源、目標(biāo)磁盤IO的壓力。
如果源中有1G數(shù)據(jù)怎么辦,或者更多數(shù)據(jù)怎么辦?
Linux下提供了一款工具rsync,它能夠?qū)崿F(xiàn)本地之間或者本地和遠(yuǎn)程之間的數(shù)據(jù)同步,它能通過分塊滾動(dòng)校驗(yàn)和算法和hash算法來計(jì)算文件的差異,源端負(fù)責(zé)計(jì)算出差異,將匹配塊引用和差異序列發(fā)回目標(biāo)端,由目標(biāo)端重新組織生成新的文件。
它的特征是:
-
分塊提取特征碼,比較差異
-
對(duì)有差異的文件,進(jìn)行增量復(fù)制
這樣大大的節(jié)省了帶寬和IO。
?
二、rsync的推拉模型
(一)服務(wù)模式
rsync的使用模型中,生成環(huán)境用的最多的還是跨主機(jī)間同步,也就是要使用服務(wù)模式。
rsync的服務(wù)模式
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]???
????? rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]?
Push: rsync [OPTION...] SRC... [USER@]HOST::DEST????
????? rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
| -v, --verbose | 詳細(xì)信息輸出 |
| -q, --quiet | 不顯示非錯(cuò)誤信息 |
| -a, --archive | 歸檔模式 |
| -r, --recursive | 遞歸目錄 |
| -z, --compress | 啟用數(shù)據(jù)壓縮 |
| --delete | 刪除目標(biāo)目錄中多余的文件 |
| --progress | 顯示進(jìn)度 |
| --password-file=FILE | 密碼文件存放路徑,注意這個(gè)文件的權(quán)限 |
?
(二)拉模型
拉模型指的是主動(dòng)去服務(wù)器的指定端口獲取數(shù)據(jù)
通過rsync服務(wù)拉模型同步:
目標(biāo)節(jié)點(diǎn)主動(dòng)的連接到源節(jié)點(diǎn)后,雙方比較文件差異,然后從源節(jié)點(diǎn)同步文件差異生成新文件以求保持一致。
目標(biāo)節(jié)點(diǎn)需要定時(shí)去訪問源節(jié)點(diǎn),時(shí)間間隔不宜過于快,也不宜過慢。
而且比較差異,是遍歷整個(gè)目錄文件,是非常占資源的事情。
從以上分析可以看出,目標(biāo)節(jié)點(diǎn)主動(dòng)拉取數(shù)據(jù)是基于查詢機(jī)制的,非常沒有效率。
那么,解決問題的辦法是使用一種機(jī)制,能夠獲取到源節(jié)點(diǎn)數(shù)據(jù)的變化之后,再啟動(dòng)同步,這將大大減少資源的占用。而Linux給我們提供了這種機(jī)制,就是inotify。
inotify: Linux從2.6.13內(nèi)核開始引入。通過inotify可以監(jiān)控文件系統(tǒng)的添加、刪除、修改、移動(dòng)等各種細(xì)微事件,利用這個(gè)內(nèi)核接口,第三方軟件可以監(jiān)控文件系統(tǒng)的各種變化,而inotify-tools就是其中一種工具。
?
(三)推模型
推模型指的是將數(shù)據(jù)主動(dòng)推送至服務(wù)器指定端口
推模型一樣存在怎樣推送、間隔多久推送的問題!
但是,推模型可以結(jié)合inotify來決定什么時(shí)候推送數(shù)據(jù)。
讓源節(jié)點(diǎn)通過inotify探查到同步目錄中文件發(fā)生了改變,然后源節(jié)點(diǎn)主動(dòng)的將文件推至目標(biāo)節(jié)點(diǎn),這將大大提高效率。
這樣,源節(jié)點(diǎn)使用inotify + rsync客戶端,目標(biāo)節(jié)點(diǎn)配置rsync的服務(wù)器。
下面就依照推模型的規(guī)劃來完成本次實(shí)驗(yàn)。
?
三、inotify + rsync的推模型方案實(shí)驗(yàn)
本次實(shí)驗(yàn)使用的操作系統(tǒng)是CentOS 6.5。
# uname -r????
2.6.32-431.el6.x86_64
其確保內(nèi)核的版本是2.6.13之上。
?
(一)目標(biāo)節(jié)點(diǎn)配置
1、準(zhǔn)備服務(wù)程序
rsync需要依賴超級(jí)守護(hù)進(jìn)程xinetd,服務(wù)默認(rèn)監(jiān)聽在TCP的873端口,客戶端連接此端口,來推送數(shù)據(jù)或者拉取數(shù)據(jù)。
# yum -y install xinetd # yum -y install rsync [root@localhost ~]# sed -i 's/yes/no/' /etc/xinetd.d/rsync [root@localhost ~]# cat /etc/xinetd.d/rsync # default: off # description: The rsync server is a good addition to an ftp server, as it \ # allows crc checksumming etc. service rsync { disable = no flags = IPv6 socket_type = stream wait = no user = root server = /usr/bin/rsync server_args = --daemon log_on_failure += USERID } ? # mkdir /tmp/data/ –v?
2、提供配置文件????
?
3、準(zhǔn)備用戶認(rèn)證文件
?
說明
write only如果是yes(true)就不許下載,也就是說,如果是no(false)就允許下載,但要檢查是否有權(quán)限。
auth users 用戶認(rèn)證
secrets file 指明用戶認(rèn)證所使用的用戶名和密碼所存儲(chǔ)的文件。注意這個(gè)文件的權(quán)限要400或者600。
?
4、啟動(dòng)服務(wù)
啟動(dòng)超級(jí)守護(hù)進(jìn)程,讓它代為監(jiān)聽TCP 873端口。
# service xinetd start Starting xinetd: [ OK ] # ss -tnlp | grep :873 LISTEN 0 64 :::873 :::* users:(("xinetd",1443,5))?
?
(二)源節(jié)點(diǎn)配置
1、安裝rsync
# yum -y install rsync # mkdir /data/ # rsync -vv rsync://tom@192.168.60.144/data/* /data/ opening tcp connection to 192.168.60.144 port 873 sending daemon args: --server --sender -vve.Ls . "data/*" Password: delta-transmission enabled a.txt test.txt ? sent 91 bytes received 189 bytes 20.74 bytes/sec total size is 0 speedup is 0.00?
2、安裝inotify-tools
# tar xf inotify-tools-3.13.tar.gz # cd inotify-tools-3.13 # ./configure # make # make install?
3、inotifywait
inotify-tools提供了有用的工具inotifywait。
| -r | 監(jiān)視目錄及其子目錄 |
| -m | 始終處于事件監(jiān)聽狀態(tài)不退出 |
| -q --quiet | 靜默,只打印時(shí)間 |
| -e --event | 指定監(jiān)聽的事件,如果不指定,監(jiān)聽所有事件 |
| --exclude | 使用擴(kuò)展正則表達(dá)式描述的排除文件 |
| --excludei | 使用擴(kuò)展正則表達(dá)式描述的排除文件,忽略大小寫 |
| --format | 指定打印的格式,類似printf。?????????? %w 發(fā)生事件的目錄名稱?????????? %f 發(fā)生事件的文件名稱?????????? %e 發(fā)生的事件?????????? %Xe 使用X分隔發(fā)生的事件?????????? %T --timefmt選項(xiàng)指定的時(shí)間格式 |
| --timefmt | 使用和strftime兼容的格式的時(shí)間格式 |
?
| access | 文件或目錄內(nèi)容被讀取 |
| modify | 文件或目錄內(nèi)容被寫入 |
| attrib | 文件或目錄屬性改變,即元數(shù)據(jù)被修改 |
| close_write | 在可寫模式打開后關(guān)閉 |
| close_nowrite | 在只讀模式打開后關(guān)閉 |
| close | 不管是否讀寫模式,只要是關(guān)閉 |
| open | 打開 |
| moved_to | 文件或目錄移動(dòng)至監(jiān)控目錄 |
| moved_from | 文件或目錄從監(jiān)控目錄移動(dòng)走 |
| move | 只要監(jiān)控目錄有移動(dòng)事件 |
| create | 在監(jiān)控目錄有文件或目錄被創(chuàng)建 |
| delete | 在監(jiān)控目錄有文件或目錄被刪除 |
| delete_self | 監(jiān)控的目錄和文件本身被刪除 |
| unmount | 包含文件或目錄的文件系統(tǒng)卸載 |
?
[ 事件分析 ]
使用下面的命令,來分析一下各種操作產(chǎn)生的事件是什么,從而分析出哪些事件是需要監(jiān)控的。
# inotifywait -rm --format "%T %w %f %e" --timefmt "%Y-%m-%d %H:%M:%S" --excludei ".*\.(swp|swx|swpx)$" /data/?
[root@localhost /]# cd /data/????
無事件
?
[root@localhost data]# ls????
2014-08-31 06:32:55 /data/? OPEN,ISDIR????
2014-08-31 06:32:55 /data/? CLOSE_NOWRITE,CLOSE,ISDIR
事件:open close_nowrite close
?
[root@localhost data]# touch test????
2014-08-31 06:35:54 /data/ test CREATE????
2014-08-31 06:35:54 /data/ test OPEN????
2014-08-31 06:35:54 /data/ test ATTRIB????
2014-08-31 06:35:54 /data/ test CLOSE_WRITE,CLOSE
事件:create open attirb close_write close
?
[root@localhost data]# mkdir content????
2014-08-31 06:36:58 /data/ content CREATE,ISDIR????
2014-08-31 06:36:58 /data/ content OPEN,ISDIR????
2014-08-31 06:36:58 /data/ content CLOSE_NOWRITE,CLOSE,ISDIR
事件:create open close_nowrite close
?
[root@localhost data]# ls content/????
2014-08-31 06:40:10 /data/ content OPEN,ISDIR????
2014-08-31 06:40:10 /data/content/? OPEN,ISDIR????
2014-08-31 06:40:10 /data/ content CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:40:10 /data/content/? CLOSE_NOWRITE,CLOSE,ISDIR
事件:open close_nowrite close
?
[root@localhost data]# cp /etc/issue content/????
2014-08-31 06:41:23 /data/? OPEN,ISDIR????
2014-08-31 06:41:23 /data/? CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:41:25 /data/content/ issue CREATE????
2014-08-31 06:41:25 /data/content/ issue OPEN????
2014-08-31 06:41:25 /data/content/ issue MODIFY????
2014-08-31 06:41:25 /data/content/ issue CLOSE_WRITE,CLOSE
事件:open close_nowrite close create open modify
?
[root@localhost data]# cat content/issue????
2014-08-31 06:44:09 /data/content/ issue OPEN????
2014-08-31 06:44:09 /data/content/ issue ACCESS????
2014-08-31 06:44:09 /data/content/ issue CLOSE_NOWRITE,CLOSE
事件:open access close_nowrite close
?
[root@localhost data]# nano testfile????
2014-08-31 07:50:35 /data/ testfile CREATE????
2014-08-31 07:50:35 /data/ testfile OPEN????
2014-08-31 07:50:35 /data/ testfile MODIFY????
2014-08-31 07:50:35 /data/ testfile CLOSE_WRITE,CLOSE
事件:create open modify close_write close
?
[root@localhost data]# vim content/issue????
2014-08-31 06:51:03 /data/? OPEN,ISDIR????
2014-08-31 06:51:03 /data/? CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:51:03 /data/? OPEN,ISDIR????
……????
2014-08-31 06:51:03 /data/content/ issue OPEN????
2014-08-31 06:51:03 /data/content/ .issue.swpx CREATE????
2014-08-31 06:51:03 /data/content/ .issue.swpx OPEN????
2014-08-31 06:51:03 /data/content/ .issue.swpx CLOSE_WRITE,CLOSE????
2014-08-31 06:51:03 /data/content/ .issue.swpx DELETE????
2014-08-31 06:51:03 /data/? OPEN,ISDIR????
2014-08-31 06:51:03 /data/? CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:51:03 /data/? OPEN,ISDIR????
2014-08-31 06:51:03 /data/? CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:51:03 /data/content/ issue CLOSE_NOWRITE,CLOSE????
2014-08-31 06:51:03 /data/content/ issue OPEN????
2014-08-31 06:51:03 /data/content/ issue ACCESS????
2014-08-31 06:51:03 /data/content/ issue CLOSE_NOWRITE,CLOSE????
2014-08-31 06:51:03 /data/? OPEN,ISDIR????
2014-08-31 06:51:03 /data/? CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:51:12 /data/? OPEN,ISDIR????
2014-08-31 06:51:12 /data/? CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:51:12 /data/content/ 4913 CREATE????
2014-08-31 06:51:12 /data/content/ 4913 OPEN????
2014-08-31 06:51:12 /data/content/ 4913 ATTRIB????
2014-08-31 06:51:12 /data/content/ 4913 CLOSE_WRITE,CLOSE????
2014-08-31 06:51:12 /data/content/ 4913 DELETE????
2014-08-31 06:51:12 /data/content/ issue MOVED_FROM????
2014-08-31 06:51:12 /data/content/ issue~ MOVED_TO????
2014-08-31 06:51:12 /data/content/ issue CREATE????
2014-08-31 06:51:12 /data/content/ issue OPEN????
2014-08-31 06:51:12 /data/content/ issue MODIFY????
2014-08-31 06:51:12 /data/content/ issue CLOSE_WRITE,CLOSE????
2014-08-31 06:51:12 /data/content/ issue ATTRIB????
2014-08-31 06:51:12 /data/content/ issue ATTRIB????
2014-08-31 06:51:12 /data/content/ issue~ DELETE????
2014-08-31 06:51:12 /data/? OPEN,ISDIR????
2014-08-31 06:51:12 /data/? CLOSE_NOWRITE,CLOSE,ISDIR
事件:create open attrib delete modify moved_from moved_to close_write close
下面是使用vim打開,無修改關(guān)閉的日志
2014-08-31 06:46:51 /data/content/ issue CLOSE_NOWRITE,CLOSE????
2014-08-31 06:46:51 /data/content/ issue OPEN????
2014-08-31 06:46:51 /data/content/ issue ACCESS????
2014-08-31 06:46:51 /data/content/ issue CLOSE_NOWRITE,CLOSE
可以看出關(guān)鍵的事件是close_nowrite
?
[root@localhost data]# mv content/issue /tmp/????
2014-08-31 06:52:48 /data/content/ issue MOVED_FROM????
[root@localhost data]# mv /tmp/issue /data/content/????
2014-08-31 06:54:55 /data/content/ issue MOVED_TO
事件:moved_from moved_to
?
[root@localhost data]# rm /data/content/issue????
2014-08-31 06:58:25 /data/content/ issue DELETE
[root@localhost data]# rm -rf /data/content????
2014-08-31 06:59:53 /data/ content OPEN,ISDIR????
2014-08-31 06:59:53 /data/content/? OPEN,ISDIR????
2014-08-31 06:59:53 /data/content/ t1.txt DELETE????
2014-08-31 06:59:53 /data/ content DELETE,ISDIR????
2014-08-31 06:59:53 /data/ content CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:59:53 /data/content/? CLOSE_NOWRITE,CLOSE,ISDIR????
2014-08-31 06:59:53 /data/content/? DELETE_SELF????
2014-08-31 06:59:53 /data/content/? IGNORED
事件:open delete delete_self close_nowrite close
?
[root@localhost data]# chmod 400 testfile
2014-08-31 08:22:53 /data/ testfile ATTRIB
事件:attrib
?
由此可見,一個(gè)監(jiān)控中的文件夾內(nèi)容改變的主要事件有:create delete attrib close_write。
選取create是因?yàn)?#xff0c;目錄的創(chuàng)建,不會(huì)發(fā)生close_write事件。
文件的創(chuàng)建,create事件產(chǎn)生,保存退出,會(huì)產(chǎn)生close_write事件。文件的修改,modify事件產(chǎn)生,保存退出,會(huì)產(chǎn)生close_write事件。所以選取close_write。
修改一個(gè)文件屬性,只會(huì)產(chǎn)生attrib事件,所以要選取它。
文件或目錄的刪除都會(huì)產(chǎn)生delete事件。
?
4、部署inotify監(jiān)控
創(chuàng)建訪問目標(biāo)節(jié)點(diǎn)的訪問密碼文件
# echo "tomadm" > /etc/rsync.accesspasswd # cat /etc/rsync.accesspasswd tomadm ? # chmod 400 /etc/rsync.accesspasswd?
5、推送測(cè)試
# rsync -avzr --delete --progress --password-file=/etc/rsync.accesspasswd /data/* rsync://tom@192.168.60.144/data/ sending incremental file list ERROR: module is read only rsync error: syntax or usage error (code 1) at main.c(866) [receiver=3.0.6] rsync: read error: Connection reset by peer (104) rsync error: error in rsync protocol data stream (code 12) at io.c(759) [sender=3.0.6]修改目標(biāo)節(jié)點(diǎn)的配置文件,修改為可寫,但不可下載。然后再次測(cè)試
# sed -i -e 's/read only.*/read only = no/' -e 's/write only.*/write only = yes/' /etc/rsyncd.conf # rsync -avzr --delete --progress --password-file=/etc/rsync.accesspasswd /data/* rsync://tom@192.168.60.144/data/ sending incremental file list apx.txt 0 100% 0.00kB/s 0:00:00 (xfer#1, to-check=3/5) issue 68 100% 0.00kB/s 0:00:00 (xfer#2, to-check=2/5) test.txt 0 100% 0.00kB/s 0:00:00 (xfer#3, to-check=1/5) ttt/ ? sent 283 bytes received 69 bytes 33.52 bytes/sec total size is 68 speedup is 0.19?
6、提供后臺(tái)運(yùn)行腳本
提供腳本/usr/local/scripts/inotesync.sh,內(nèi)容如下
#!/bin/bash prog=inotesync dir=/data/ user=tom romote=192.168.60.144 logfile=/var/log/${prog}.log ? { /usr/local/bin/inotifywait -rmq -e create,attrib,delete,close_write --format "%T %e %w%f" --timefmt "%Y-%m-%d %H:%M:%S" $dir | while read line do /usr/bin/rsync -avzr --delete --progress --password-file=/etc/rsync.accesspasswd $dir rsync://$user@$romote$dir done } >> $logfile & ? ? ? ? # chmod +x /usr/local/scripts/inotesync.sh ? # echo "/usr/local/scripts/inotesync.sh" >> /etc/rc.local重啟測(cè)試成功。
?
腳本說明:
1、在rc.local尾部追加腳本路徑,使其啟動(dòng)時(shí)運(yùn)行
2、inotifywait、rsync使用絕對(duì)路徑,否則腳本將不能正常運(yùn)行,因?yàn)榇藭r(shí)環(huán)境變量PATH還沒有起作用
3、為了排錯(cuò)或者查看信息,使用一個(gè)花括號(hào)將語句塊套起來,這樣語句塊內(nèi)的所有的日志輸出重定向到日志文件中
4、使用&符號(hào),讓命令后臺(tái)執(zhí)行
?
至此,使用inotify+rsync的推模型實(shí)驗(yàn)完成。
?
四、總結(jié)
inotify+rsync的推模型,很好的解決了拉模型中的幾個(gè)問題,做到了有變化再做同步。但是使用inotify來監(jiān)控文件夾,只是在監(jiān)控的事件發(fā)生的時(shí)候,觸發(fā)了一個(gè)事件,而每觸發(fā)一個(gè)事件,rsync都要遍歷比較所有文件和目錄。當(dāng)目錄中文件非常多的時(shí)候效率也不高。
可以考慮從inotifywait的輸出信息中,提取被創(chuàng)建、改變的文件,推送到目標(biāo)節(jié)點(diǎn)。
?
參考資料
http://en.wikipedia.org/wiki/Rsync
http://zh.wikipedia.org/zh/Inotify
http://tutorials.jenkov.com/rsync/index.html
http://rsync.samba.org/tech_report/tech_report.html
http://en.wikipedia.org/wiki/Rolling_hash
http://blog.csdn.net/liuaigui/article/details/5793706
http://www.ibm.com/developerworks/cn/linux/l-inotify/
http://www.cnblogs.com/jingzhishen/p/3738637.html
轉(zhuǎn)載于:https://blog.51cto.com/me2xp/1549624
總結(jié)
以上是生活随笔為你收集整理的rsync推拉模型及结合inotify实现推模型自动同步的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 编码规范8(编程规约-注释规约
- 下一篇: 企业技术