rsync+inotify實時同步環境部署記錄

 

隨着應用系統規模的不斷擴大,對數據的安全性和可靠性也提出的更好的要求,rsync在高端業務系統中也逐漸暴露出了不少不足。
首先,rsync在同步數據時,須要掃描全部文件後進行比對,進行差量傳輸。若是文件數量達到了百萬甚至千萬量級,掃描全部文件將是很是耗時的,而且正在發生變化的每每是其中不多的一部分,這是很是低效的方式。
其次,rsync不能實時的去監測、同步數據,雖然它能夠經過linux守護進程的方式進行觸發同步,可是兩次觸發動做必定會有時間差,這樣就致使了服務端和客戶端數據可能出現不一致,沒法在應用故障時徹底的恢復數據。html

基於以上兩種狀況,能夠使用rsync+inotify的組合來解決,能夠實現數據的實時同步linux

inotify是一種強大的、細粒度的、異步的文件系統事件控制機制。linux內核從2.6.13起,加入了inotify支持,經過inotify能夠監控文件系統中添加、刪除、修改、移動等各類事件,利用這個內核接口,第三方軟件就能夠監控文件系統下文件的各類變化狀況,而inotify-tools正是實施監控的軟件。
在使用rsync首次全量同步後,結合inotify對源目錄進行實時監控,只有有文件變更或新文件產生,就會馬上同步到目標目錄下,很是高效使用!nginx

-----------------------------------------------------------------------------------------------------------
下面分享下我在實際工做中的一個rsync+inotify案例(實際上是個網站圖片備份方案):c++

需求說明:
分別將
192.168.1.106的/Data/fangfull_upload和/Data/erp_upload
192.168.1.57的/Data/xqsj_upload/和/Data/fanghu_upload_src
192.168.1.139的/Data/Static_img/webroot/ssapp-prod和/usr/local/nginx/html/ssapp.prod
實時同步到
192.168.1.5的/home/backup/image-back目錄下對應的fangfull_upload、erp_upload、xqsj_upload、fanghu_upload_src、ssapp-prod和ssapp.prod目錄。git

這樣的話:
(1)192.168.1.10六、192.168.1.5七、192.168.1.139這三臺服務器是源服務器,做爲rsync的客戶端,部署rsync+inotify。
(2)192.168.1.5是目標服務器,做爲rsync的服務端。只須要安裝配置rsync便可,不須要安裝inotify。github

---------------------------------------------------------------
詳細部署過程,記錄以下:web

第一部分:在目標服務器192.168.1.5上部署rsync服務端。vim

1)關閉selinux
[root@bastion-IDC ~]# vim /etc/selinux/config
SELINUX=disabled
[root@bastion-IDC ~]# setenforce 0數組

2)防火牆上容許以上三臺源服務器訪問它的22端口和873端口
[root@bastion-IDC ~]# vim /etc/sysconfig/iptables
.......
.......
-A INPUT -s 192.168.1.106 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -s 192.168.1.57 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -s 192.168.1.139 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -s 192.168.1.106 -m state --state NEW -m tcp -p tcp --dport 873 -j ACCEPT
-A INPUT -s 192.168.1.57 -m state --state NEW -m tcp -p tcp --dport 873 -j ACCEPT
-A INPUT -s 192.168.1.139 -m state --state NEW -m tcp -p tcp --dport 873 -j ACCEPT安全

[root@bastion-IDC ~]# /etc/init.d/iptables restart

如若hosts.allow裏面作了限制,一樣也要開放以上三臺源服務器的權限
[root@bastion-IDC ~]# vim /etc/hosts.allow
#
# hosts.allow This file contains access rules which are used to
# allow or deny connections to network services that
# either use the tcp_wrappers library or that have been
# started through a tcp_wrappers-enabled xinetd.
#
# See 'man 5 hosts_options' and 'man 5 hosts_access'
# for information on rule syntax.
# See 'man tcpd' for information on tcp_wrappers
#
sshd:192.168.1.106,192.168.1.57,192.168.1.139:allow
sshd:all:deny
[root@bastion-IDC ~]# cat /etc/hosts.deny
#
# hosts.deny This file contains access rules which are used to
# deny connections to network services that either use
# the tcp_wrappers library or that have been
# started through a tcp_wrappers-enabled xinetd.
#
# The rules in this file can also be set up in
# /etc/hosts.allow with a 'deny' option instead.
#
# See 'man 5 hosts_options' and 'man 5 hosts_access'
# for information on rule syntax.
# See 'man tcpd' for information on tcp_wrappers
#

3)安裝部署rsync服務
注意:CentOS中是以xinetd來管理Rsync服務的
[root@bastion-IDC ~]# yum install rsync xinetd
[root@bastion-IDC ~]# vim /etc/xinetd.d/rsync
.....
disable = no               #由默認的yes改成no,設置開機啓動rsync

啓動xineted服務
[root@bastion-IDC ~]# /etc/init.d/xinetd start

建立/etc/rsyncd.conf文件,並配置同步策略。添加以下代碼:
[root@bastion-IDC ~]# vim /etc/rsyncd.conf
log file = /var/log/rsyncd.log          #日誌文件位置,啓動rsync後自動產生這個文件,無需提早建立
pidfile = /var/run/rsyncd.pid           #pid文件的存放位置
lock file = /var/run/rsync.lock        #支持max connections參數的鎖文件
secrets file = /etc/rsync.pass         #用戶認證配置文件,裏面保存用戶名稱和密碼,後面會建立這個文件
motd file = /etc/rsyncd.Motd          #rsync啓動時歡迎信息頁面文件位置(本身建立這個文件,內容隨便自定義)

[fangfull_upload]                            #自定義名稱
path = /home/backup/image-back/fangfull_upload           #rsync服務端數據目錄路徑,即同步到目標目錄後的存放路徑
comment = fangfull_upload                                             #模塊名稱與[fangfull_upload]自定義名稱相同
uid = nobody                                 #設置rsync運行的uid權限。這個要保證同步到目標目錄後的權限和源目錄一致,即都是nobody!
gid = nobody                                #設置rsync運行的gid權限。
port=873                                    #默認的rsync端口
use chroot = no                          #默認爲true,修改成no或false,增長對目錄文件軟鏈接的備份
read only = no                            #設置rsync服務端文件爲讀寫權限
list = no                                      #不顯示rsync服務端資源列表
max connections = 200              #最大鏈接數
timeout = 600                           #設置超時時間
auth users = RSYNC_USER          #執行數據同步的用戶名,須要後面手動設置。能夠設置多個,用英文狀態下逗號隔開
hosts allow = 192.168.1.106        #容許進行數據同步的客戶端IP地址,能夠設置多個,用英文狀態下逗號隔開
hosts deny = 192.168.1.194       #禁止數據同步的客戶端IP地址,能夠設置多個,用英文狀態下逗號隔開(若是沒有禁止,就不用設置這一行)

[erp_upload]
path = /home/backup/image-back/erp_upload
comment = erp_upload
uid = nobody
gid = nobody
port=873
use chroot = no
read only = no
list = no
max connections = 200
timeout = 600
auth users = RSYNC_USER
hosts allow = 192.168.1.106

[xqsj_upload]
path = /home/backup/image-back/xqsj_upload
comment = xqsj_upload
uid = nobody
gid = nobody
port=873
use chroot = no
read only = no
list = no
max connections = 200
timeout = 600
auth users = RSYNC_USER
hosts allow = 192.168.1.57

[fanghu_upload_src]
path = /home/backup/image-back/fanghu_upload_src
comment = fanghu_upload_src
uid = nobody
gid = nobody
port=873
use chroot = no
read only = no
list = no
max connections = 200
timeout = 600
auth users = RSYNC_USER
hosts allow = 192.168.1.57

[ssapp-prod]
path = /home/backup/image-back/ssapp-prod
comment = ssapp-prod
uid = nginx
gid = nginx
port=873
use chroot = no
read only = no
list = no
max connections = 200
timeout = 600
auth users = RSYNC_USER
hosts allow = 192.168.1.139

[ssapp.prod]
path = /home/backup/image-back/ssapp.prod
comment = ssapp.prod
uid = nginx
gid = nginx
port=873
use chroot = no
read only = no
list = no
max connections = 200
timeout = 600
auth users = RSYNC_USER
hosts allow = 192.168.1.139

建立用戶認證文件 (多個模塊用的是這同一個認證文件)
[root@bastion-IDC ~]# vim /etc/rsync.pass
RSYNC_USER:123456@rsync

設置文件權限,即rsyncd.conf和rsync.pass認證文件都是600權限!
[root@bastion-IDC ~]# chmod 600 /etc/rsyncd.conf
[root@bastion-IDC ~]# chmod 600 /etc/rsync.pass

重啓rsync服務
[root@bastion-IDC ~]# /etc/init.d/xinetd restart
[root@bastion-IDC ~]# lsof -i:873
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
xinetd 22041 root 5u IPv6 3336440 0t0 TCP *:rsync (LISTEN)

4)最後,建立rsync同步過來後的目標目錄
[root@bastion-IDC ~]# cd /home/backup/image-back/
[root@bastion-IDC image-back]# mkdir fangfull_upload erp_upload xqsj_upload fanghu_upload_src ssapp-prod ssapp.prod
[root@bastion-IDC image-back]# ll
total 40
drwxr-xr-x. 8 nobody nobody 4096 Jun 12 17:25 erp_upload
drwxrwxrwx. 584 nobody nobody 20480 Oct 26 13:41 fangfull_upload
drwxr-xr-x. 11 nobody nobody 4096 Oct 26 14:23 fanghu_upload_src
drwxr-xr-x. 10 nginx nginx 4096 Oct 26 13:44 ssapp-prod
drwxr-xr-x. 7 nginx nginx 4096 Oct 24 18:01 ssapp.prod
drwxrwxrwx. 144 nobody nobody 4096 Sep 26 11:25 xqsj_upload

第二部分:在源服務器192.168.1.10六、192.168.1.5七、192.168.1.139部署rsync客戶端和inotify監控。

1)三臺機器一樣操做
關閉selinux,作爲客戶端的rsync能夠不用在iptables裏開放873端口
[root@static-img ~]# vim /etc/selinux/config
SELINUX=disabled
[root@static-img ~]# setenforce 0

2)三臺機器一樣操做
安裝rsync
[root@static-img ~]# yum install rsync xinetd
[root@static-img ~]# vim /etc/xinetd.d/rsync
.....
disable = no                     #由默認的yes改成no,設置開機啓動rsync

啓動rsync服務
[root@static-img ~]# /etc/init.d/xinetd start
[root@static-img ~]# lsof -i:873
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
xinetd 3268 root 5u IPv4 4139812 0t0 TCP *:rsync (LISTEN)

建立同步的密碼文件,這個文件名能夠跟服務端的認證文件不同,可是裏面的密碼必須一致!用於rsync同步命令中。不過,最好兩邊的文件設置成同樣,便於管理
[root@static-img ~]# vim /etc/rsync.pass
123456@rsync

設置rsync.pass密碼文件爲600權限
[root@static-img ~]# chmod 600 /etc/rsync.pass

3)三臺機器一樣操做
查看服務器內核是否支持inotify,出現下面的內容,說明服務器內核支持inotify
[root@static-img ~]# ll /proc/sys/fs/inotify
total 0
-rw-r--r-- 1 root root 0 Oct 26 12:03 max_queued_events
-rw-r--r-- 1 root root 0 Oct 26 12:03 max_user_instances
-rw-r--r-- 1 root root 0 Oct 26 12:03 max_user_watches

注意:Linux下支持inotify的內核最小爲2.6.13,能夠輸入命令:uname -a查看內核
CentOS 5.X 內核爲2.6.18,默認已經支持inotify
[root@static-img ~]# uname -a
Linux static-img 2.6.32-573.22.1.el6.x86_64 #1 SMP Wed Mar 23 03:35:39 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

下面開始安裝inotify-tools
[root@static-img ~]# yum install make gcc gcc-c++                          #安裝編譯工具
[root@static-img ~]# cd /usr/local/src
[root@static-img src]# wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz
[root@static-img src]# tar zxvf inotify-tools-3.14.tar.gz
[root@static-img src]# cd inotify-tools-3.14
[root@static-img inotify-tools-3.14]# ./configure --prefix=/usr/local/inotify
[root@static-img inotify-tools-3.14]# make && make install

發現已經成功安裝inotify-tools了
[root@static-img inotify-tools-3.14]# ll -d /usr/local/inotify/
drwxr-xr-x 6 root root 4096 Oct 26 12:01 /usr/local/inotify/

設置系統環境變量
[root@static-img ~]# vim /etc/profile
......
export PATH=$PATH:/usr/local/inotify/bin
[root@static-img ~]# source /etc/profile

添加庫文件
[root@static-img ~]# vim /etc/ld.so.conf
/usr/local/inotify/lib
[root@static-img ~]# ldconfig

修改inotify默認參數(inotify默認內核參數值過小)
查看系統默認參數值
[root@static-img ~]# sysctl -a | grep max_queued_events
fs.inotify.max_queued_events = 16384
[root@static-img ~]# sysctl -a | grep max_user_watches
fs.inotify.max_user_watches = 8192
[root@static-img ~]# sysctl -a | grep max_user_instances
fs.inotify.max_user_instances = 128

修改參數:
[root@static-img ~]# sysctl -w fs.inotify.max_queued_events="99999999"
[root@static-img ~]# sysctl -w fs.inotify.max_user_watches="99999999"
[root@static-img ~]# sysctl -w fs.inotify.max_user_instances="65535"

參數說明:
max_queued_events:
inotify隊列最大長度,若是值過小,會出現"** Event Queue Overflow **"錯誤,致使監控文件不許確
max_user_watches:
要同步的文件包含多少目錄,能夠用:find /Data/xqsj_upload -type d | wc -l 統計這些源目錄下的目錄數,必須保證max_user_watches值大於統計結果(這裏/Data/xqsj_upload爲同步的源文件目錄)
max_user_instances:
每一個用戶建立inotify實例最大值


4)接着執行同步操做:
分別在三臺源服務器上執行rsync首次全量同步的操做(加--delete參數,保持目標目錄和源目錄下文件絕對一致)
-------------------------------------------------------------------------------------------------------------------------------------------------------
在192.168.1.106服務器上
第一次全量同步:
[root@fangfull_web ~]# rsync -avH --port=873 --progress --delete /Data/fangfull_upload/ RSYNC_USER@192.168.1.5::fangfull_upload --password-file=/etc/rsync.pass
[root@fangfull_web ~]# rsync -avH --port=873 --progress --delete /Data/erp_upload/ RSYNC_USER@192.168.1.5::erp_upload --password-file=/etc/rsync.pass

待第一次rsync全量同步完成後,就進行rsync+inotify實時同步腳本操做。
實時同步腳本里添加的是--delete-before參數,而不是--delete參數(第一次全量同步時rsync用的參數),兩者區別:
--delete參數:表示rsync同步前,暴力刪除目標目錄中的全部文件,而後再執行同步操做。
--delete-before參數:表示rsync同步前,會先對目標目錄進行一次掃描檢索,刪除目標目錄中對比源目錄的多餘文件,而後再執行同步操做。顯然比--delete參數安全些。
[root@fangfull_web1 ~]# cd /home/rsync/
[root@fangfull_web1 rsync]# cat rsync_fangfull_upload_inotify.sh
#!/bin/bash
SRCDIR=/Data/fangfull_upload/
USER=RSYNC_USER
IP=192.168.1.5
DESTDIR=fangfull_upload
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $SRCDIR | while read file
do
/usr/bin/rsync -avH --port=873 --progress --delete-before $SRCDIR $USER@$IP::$DESTDIR --password-file=/etc/rsync.pass
echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
done
[root@fangfull_web1 rsync]# cat rsync_erp_upload_inotify.sh
#!/bin/bash
SRCDIR=/Data/erp_upload/
USER=RSYNC_USER
IP=192.168.1.5
DESTDIR=erp_upload
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $SRCDIR | while read file
do
/usr/bin/rsync -avH --port=873 --progress --delete-before $SRCDIR $USER@$IP::$DESTDIR --password-file=/etc/rsync.pass
echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
done

而後啓動同步腳本,放在後臺執行!
[root@fangfull_web1 rsync]# nohup sh rsync_fangfull_upload_inotify.sh &
[root@fangfull_web1 rsync]# nohup sh rsync_erp_upload_inotify.sh &

檢查下是否腳本啓動成功了
[root@fangfull_web1 rsync]# ps -ef|grep inotify
root 11390 1 0 13:41 ? 00:00:00 sh rsync_erp_upload_inotify.sh
root 11392 11390 0 13:41 ? 00:00:00 sh rsync_erp_upload_inotify.sh
root 11397 1 0 13:41 ? 00:00:00 sh rsync_fangfull_upload_inotify.sh
root 11399 11397 0 13:41 ? 00:00:00 sh rsync_fangfull_upload_inotify.sh
root 21842 11702 0 17:22 pts/0 00:00:00 grep --color=auto inotify

最後進行測試:
好比在源目錄/Data/fangfull_upload中建立一個文件或目錄,會自動實時同步到目標機器192.168.1.5的目標目錄/home/backup/image-back/fangfull_upload中。

--------------------------------------------------------------------------------------------------------------------------------------------------
在192.168.1.57服務器上
第一次全量同步:
[root@xqsj_web ~]# rsync -avH --port=873 --progress --delete /Data/xqsj_upload/ RSYNC_USER@192.168.1.5::xqsj_upload --password-file=/etc/rsync.pass
[root@xqsj_web ~]# rsync -avH --port=873 --progress --delete /Data/fanghu_upload_src/ RSYNC_USER@192.168.1.5::fanghu_upload_src --password-file=/etc/rsync.pass

rsync+inotify實時同步:
[root@xqsj_web1 ~]# cd /home/rsync/
[root@xqsj_web1 rsync]# cat rsync_xqsj_upload_inotify.sh
#!/bin/bash
SRCDIR=/Data/xqsj_upload/
USER=RSYNC_USER
IP=192.168.1.5
DESTDIR=xqsj_upload
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $SRCDIR | while read file
do
/usr/bin/rsync -avH --port=873 --progress --delete-before $SRCDIR $USER@$IP::$DESTDIR --password-file=/etc/rsync.pass
echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
done
[root@xqsj_web1 rsync]# cat rsync_fanghu_upload_src_inotify.sh
#!/bin/bash
SRCDIR=/Data/fanghu_upload_src/
USER=RSYNC_USER
IP=192.168.1.5
DESTDIR=fanghu_upload_src
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $SRCDIR | while read file
do
/usr/bin/rsync -avH --port=873 --progress --delete-before $SRCDIR $USER@$IP::$DESTDIR --password-file=/etc/rsync.pass
echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
done

而後啓動同步腳本,放在後臺執行!
[root@fangfull_web1 rsync]# nohup sh rsync_xqsj_upload_inotify.sh &
[root@fangfull_web1 rsync]# nohup rsync_fanghu_upload_src_inotify.sh &

最後進行測試:
好比在源目錄/Data/xqsj_upload中建立一個文件或目錄,會自動實時同步到目標機器192.168.1.5的目標目錄/home/backup/image-back/xqsj_upload中。

--------------------------------------------
在192.168.1.139服務器上
第一次全量同步:
[root@static-img ~]# rsync -avH --port=873 --progress --delete /Data/Static_img/webroot/ssapp-prod/ RSYNC_USER@192.168.1.5::ssapp-prod --password-file=/etc/rsync.pass
[root@static-img ~]# rsync -avH --port=873 --progress --delete /usr/local/nginx/html/ssapp.prod/ RSYNC_USER@192.168.1.5::ssapp.prod --password-file=/etc/rsync.pass

rsync+inotify實時同步:
[root@static-img ~]# cd /home/rsync/
[root@static-img rsync]# cat rsync_ssapp-prod_inotify.sh
#!/bin/bash
SRCDIR=/Data/Static_img/webroot/ssapp-prod/
USER=RSYNC_USER
IP=192.168.1.5
DESTDIR=ssapp-prod
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $SRCDIR | while read file
do
/usr/bin/rsync -avH --port=873 --progress --delete-before $SRCDIR $USER@$IP::$DESTDIR --password-file=/etc/rsync.pass
echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
done

[root@static-img rsync]# cat rsync_ssapp.prod_inotify.sh
#!/bin/bash
SRCDIR=/usr/local/nginx/html/ssapp.prod/
USER=RSYNC_USER
IP=192.168.1.5
DESTDIR=ssapp.prod
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $SRCDIR | while read file
do
/usr/bin/rsync -avH --port=873 --progress --delete-before $SRCDIR $USER@$IP::$DESTDIR --password-file=/etc/rsync.pass
echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
done

而後啓動同步腳本,放在後臺執行!
[root@fangfull_web1 rsync]# nohup sh rsync_ssapp-prod_inotify.sh &
[root@fangfull_web1 rsync]# nohup rsync_ssapp.prod_inotify.sh &

最後進行測試:
好比在源目錄/Data/Static_img/webroot/ssapp-prod中建立一個文件或目錄,會自動實時同步到目標機器192.168.1.5的目標目錄/home/backup/image-back/ssapp-prod中。

若是在同步過程當中,發現中途報錯!重複執行同步命令一直是報這個錯誤:
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at
main.c(1505)

最後發現緣由:
是由於在同步的時候,源目錄下有軟連接文件!
rsync同步軟連接文件,應該加參數-l

因此,最好在使用rsync同步命令的時候,後面跟-avpgolr參數組合(將上面的-avH改爲-avpgolr)-a:遞歸-v:打印詳細過程-p:保持文件屬性-g:文件所屬組不變-o:文件所屬者不變-l:軟鏈接屬性-r:同步目錄時的參數

相關文章
相關標籤/搜索