天天看點

sersync:基于 rsync + inotify 實作資料實時同步

sersync:基于 rsync + inotify 實作資料實時同步

<a target="_blank"></a>

提到資料同步就必然會談到<code>rsync</code>,一般簡單的伺服器資料傳輸會使用<code>ftp/sftp</code>等方式,但是這樣的方式效率不高,不支援差異化增量同步也不支援實時傳輸。針對資料實時同步需求大多數人會選擇<code>rsync+inotify-tools</code>的解決方案,但是這樣的方案也存在一些缺陷(文章中會具體指出),<code>sersync</code>是國人基于前兩者開發的工具,不僅保留了優點同時還強化了實時監控,檔案過濾,簡化配置等功能,幫助使用者提高運作效率,節省時間和網絡資源。

可靠高效的資料實時同步方式
synchronize files and folders between servers -using inotiy and rsync with c++ 伺服器實時同步檔案,伺服器鏡像解決方案

sersync主要用于伺服器同步,web鏡像等功能。基于boost1.43.0,inotify api,rsync command.開發。目前使用的比較多的同步解決方案是inotify-tools+rsync ,另外一個是google開源項目openduckbill(依賴于inotify- tools),這兩個都是基于腳本語言編寫的。相比較上面兩個項目,本項目優點是:

sersync是使用c++編寫,而且對linux系統檔案系統産生的臨時檔案和重複的檔案操作進行過濾(詳細見附錄,這個過濾腳本程式沒有實作),是以在結合rsync同步的時候,節省了運作時耗和網絡資源。是以更快。

相比較上面兩個項目,sersync配置起來很簡單,其中bin目錄下已經有基本上靜态編譯的2進制檔案,配合bin目錄下的xml配置檔案直接使用即可。

另外本項目相比較其他腳本開源項目,使用多線程進行同步,尤其在同步較大檔案時,能夠保證多個伺服器實時保持同步狀态。

本項目有出錯處理機制,通過失敗隊列對出錯的檔案重新同步,如果仍舊失敗,則按設定時長對同步失敗的檔案重新同步。

本項目自帶crontab功能,隻需在xml配置檔案中開啟,即可按您的要求,隔一段時間整體同步一次。無需再額外配置crontab功能。

本項目socket與http插件擴充,滿足您二次開發的需要。

針對上圖的設計架構,這裡做幾點說明,來幫助大家閱讀和了解該圖

1 ) 線程組線程是等待線程隊列的守護線程,當事件隊列中有事件産生的時候,線程組守護線程就會逐個喚醒同步線程。當隊列中 inotify 事件較多的時候,同步線程就會被全部喚醒一起工作。這樣設計的目的是為了能夠同時處理多個 inotify 事件,進而提升伺服器的并發同步能力。同步線程的最佳數量=核數 x 2 + 2。

2 ) 那麼之是以稱之為線程組線程,是因為每個線程在工作的時候,會根據伺服器上新寫入檔案的數量去建立子線程,子線程可以保證所有的檔案與各個伺服器同時同步。當要同步的檔案較大的時候,這樣的設計可以保證每個遠端伺服器都可以同時獲得需要同步的檔案。

3 ) 服務線程的作用有三個:

處理同步失敗的檔案,将這些檔案再次同步,對于再次同步失敗的檔案會生成 rsync_fail_log.sh 腳本,記錄失敗的事件。

每隔10個小時執行 rsync_fail_log.sh 腳本一次,同時清空腳本。

crontab功能,可以每隔一定時間,将所有路徑整體同步一次。

4 ) 過濾隊列的建立是為了過濾短時間内産生的重複的inotify資訊,例如在删除檔案夾的時候,inotify就會同時産生删除檔案夾裡的檔案與删除檔案夾的事件,通過過濾隊列,當删除檔案夾事件産生的時候,會将之前加入隊列的删除檔案的事件全部過濾掉,這樣隻産生一條删除檔案夾的事件,進而減輕了同步的負擔。同時對于修改檔案的操作的時候,會産生臨時檔案的重複操作。

注意主從配置的差別,記得調整selinux和防火牆

伺服器a(主伺服器)

伺服器b(從伺服器/備份伺服器)

rsync預設tcp端口為873

在伺服器b上安裝rsync:

<code>cd /app/local</code>

<code>wget http://rsync.samba.org/ftp/rsync/src/rsync-3.1.1.tar.gz</code>

<code>tar zxf rsync-3.1.1.tar.gz</code>

<code>cd rsync-3.1.1</code>

<code>./configure</code>

<code>make &amp;&amp; make install</code>

設定rsync的配置檔案:

<code>vi /etc/rsyncd.conf</code>

<code>#伺服器b上的rsyncd.conf檔案内容</code>

<code>uid=root</code>

<code>gid=root</code>

<code>#最大連接配接數</code>

<code>max connections=36000</code>

<code>#預設為true,修改為no,增加對目錄檔案軟連接配接的備份</code>

<code>use chroot=no</code>

<code>#定義日志存放位置</code>

<code>log file=/var/log/rsyncd.log</code>

<code>#忽略無關錯誤</code>

<code>ignore errors = yes</code>

<code>#設定rsync服務端檔案為讀寫權限</code>

<code>read only = no</code>

<code>#認證的使用者名與系統帳戶無關在認證檔案做配置,如果沒有這行則表明是匿名</code>

<code>auth users = rsync</code>

<code>#密碼認證檔案,格式(虛拟使用者名:密碼)</code>

<code>secrets file = /etc/rsync.pass</code>

<code>#這裡是認證的子產品名,在client端需要指定,可以設定多個子產品和路徑</code>

<code>[rsync]</code>

<code>#自定義注釋</code>

<code>comment = rsync</code>

<code>#同步到b伺服器的檔案存放的路徑</code>

<code>path=/app/data/site/</code>

<code>[img]</code>

<code>comment = img</code>

<code>path=/app/data/site/img</code>

建立rsync認證檔案 可以設定多個,每行一個使用者名:密碼,注意中間以“:”分割

<code>echo "rsync:rsync" &gt; /etc/rsync.pass</code>

設定檔案所有者讀取、寫入權限:

<code>chmod 600 /etc/rsyncd.conf</code>

<code>chmod 600 /etc/rsync.pass</code>

啟動伺服器b上的rsync服務:

<code># rsync --daemon -v</code>

<code>rsync --daemon</code>

監聽端口873:

<code>netstat -an | grep 873</code>

<code>lsof -i tcp:873</code>

<code></code>

<code>command pid user fd type device size/off node name</code>

<code>rsync 31445 root 4u ipv4 443872 0t0 tcp *:rsync (listen)</code>

<code>rsync 31445 root 5u ipv6 443873 0t0 tcp *:rsync (listen)</code>

設定rsync為服務啟動項(可選):

<code>echo "/usr/local/bin/rsync --daemon" &gt;&gt; /etc/rc.local</code>

要 kill rsync 程序,不要用 kill -hup {pid} 的方式重新開機程序,以下3種方式任選:

<code># ps -ef|grep rsync|grep -v grep|awk '{print $2}'|xargs kill -9</code>

<code># cat /var/run/rsyncd.pid | xargs kill -9</code>

<code>pkill rsync</code>

再次啟動:

<code>/usr/local/bin/rsync --daemon</code>

安裝rsync:

安裝inotify-tools:

<code>wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz</code>

<code>tar zxf inotify-tools-3.14.tar.gz</code>

<code>cd inotify-tools-3.14</code>

<code>./configure --prefix=/app/local/inotify</code>

安裝sersync:

<code>wget https://sersync.googlecode.com/files/sersync2.5.4_64bit_binary_stable_final.tar.gz</code>

<code>tar zxf sersync2.5.4_64bit_binary_stable_final.tar.gz</code>

<code>mv /app/local/gnu-linux-x86/ /app/local/sersync</code>

<code>cd /app/local/sersync</code>

配置下密碼檔案,因為這個密碼是要通路伺服器b需要的密碼和上面伺服器b的密碼必須一緻:

<code>echo "rsync" &gt; /app/local/sersync/user.pass</code>

修改權限:

<code>chmod 600 /app/local/sersync/user.pass</code>

修改confxml.conf:

<code>vi /app/local/sersync/confxml.xml</code>

<code>&lt;?xml version="1.0" encoding="iso-8859-1"?&gt;</code>

<code>&lt;head version="2.5"&gt;</code>

<code>&lt;host hostip="localhost" port="8008"&gt;&lt;/host&gt;</code>

<code>&lt;debug start="true"/&gt;</code>

<code>&lt;filesystem xfs="false"/&gt;</code>

<code>&lt;filter start="false"&gt;</code>

<code>&lt;exclude expression="(.*)\.php"&gt;&lt;/exclude&gt;</code>

<code>&lt;exclude expression="^data/*"&gt;&lt;/exclude&gt;</code>

<code>&lt;/filter&gt;</code>

<code>&lt;inotify&gt;</code>

<code>&lt;delete start="true"/&gt;</code>

<code>&lt;createfolder start="true"/&gt;</code>

<code>&lt;createfile start="false"/&gt;</code>

<code>&lt;closewrite start="true"/&gt;</code>

<code>&lt;movefrom start="true"/&gt;</code>

<code>&lt;moveto start="true"/&gt;</code>

<code>&lt;attrib start="false"/&gt;</code>

<code>&lt;modify start="false"/&gt;</code>

<code>&lt;/inotify&gt;</code>

<code>&lt;sersync&gt;</code>

<code>&lt;localpath watch="/home/"&gt; &lt;!-- 這裡填寫伺服器a要同步的檔案夾路徑--&gt;</code>

<code>&lt;remote ip="8.8.8.8" name="rsync"/&gt; &lt;!-- 這裡填寫伺服器b的ip位址和子產品名--&gt;</code>

<code>&lt;!--&lt;remote ip="192.168.28.39" name="tongbu"/&gt;--&gt;</code>

<code>&lt;!--&lt;remote ip="192.168.28.40" name="tongbu"/&gt;--&gt;</code>

<code>&lt;/localpath&gt;</code>

<code>&lt;rsync&gt;</code>

<code>&lt;commonparams params="-artuz"/&gt;</code>

<code>&lt;auth start="true" users="rsync" passwordfile="/app/local/sersync/user.pass"/&gt; &lt;!-- rsync+密碼檔案 這裡填寫伺服器b的認證資訊--&gt;</code>

<code>&lt;userdefinedport start="false" port="874"/&gt;&lt;!-- port=874 --&gt;</code>

<code>&lt;timeout start="false" time="100"/&gt;&lt;!-- timeout=100 --&gt;</code>

<code>&lt;ssh start="false"/&gt;</code>

<code>&lt;/rsync&gt;</code>

<code>&lt;faillog path="/tmp/rsync_fail_log.sh" timetoexecute="60"/&gt;&lt;!--default every 60mins execute once--&gt;&lt;!-- 修改失敗日志記錄(可選)--&gt;</code>

<code>&lt;crontab start="false" schedule="600"&gt;&lt;!--600mins--&gt;</code>

<code>&lt;crontabfilter start="false"&gt;</code>

<code>&lt;exclude expression="*.php"&gt;&lt;/exclude&gt;</code>

<code>&lt;exclude expression="info/*"&gt;&lt;/exclude&gt;</code>

<code>&lt;/crontabfilter&gt;</code>

<code>&lt;/crontab&gt;</code>

<code>&lt;plugin start="false" name="command"/&gt;</code>

<code>&lt;/sersync&gt;</code>

<code>&lt;!-- 下面這些有關于插件你可以忽略了 --&gt;</code>

<code>&lt;plugin name="command"&gt;</code>

<code>&lt;param prefix="/bin/sh" suffix="" ignoreerror="true"/&gt; &lt;!--prefix /opt/tongbu/mmm.sh suffix--&gt;</code>

<code>&lt;include expression="(.*)\.php"/&gt;</code>

<code>&lt;include expression="(.*)\.sh"/&gt;</code>

<code>&lt;/plugin&gt;</code>

<code>&lt;plugin name="socket"&gt;</code>

<code>&lt;localpath watch="/home/demo"&gt;</code>

<code>&lt;deshost ip="210.36.158.xxx" port="8009"/&gt;</code>

<code>&lt;plugin name="refreshcdn"&gt;</code>

<code>&lt;localpath watch="/data0/htdocs/cdn.markdream.com/site/"&gt;</code>

<code>&lt;cdninfo domainname="cdn.chinacache.com" port="80" username="xxxx" passwd="xxxx"/&gt;</code>

<code>&lt;sendurl base="http://cdn.markdream.com/cms"/&gt;</code>

<code>&lt;regexurl regex="false" match="cdn.markdream.com/site([/a-za-z0-9]*).cdn.markdream.com/images"/&gt;</code>

<code>&lt;/head&gt;</code>

運作sersync:

<code>nohup /app/local/sersync/sersync2 -r -d -o /app/local/sersync/confxml.xml &gt;/app/local/sersync/rsync.log 2&gt;&amp;1 &amp;</code>

<code>nohup /app/local/sersync/sersync2 -r -d -o /app/local/sersync/img.xml &gt;/app/local/sersync/img.log 2&gt;&amp;1 &amp;</code>

-d:啟用守護程序模式

-r:在監控前,将監控目錄與遠端主機用rsync指令推送一遍

-n: 指定開啟守護線程的數量,預設為10個

-o:指定配置檔案,預設使用confxml.xml檔案

本文來自雲栖社群合作夥伴“linux中國”,原文釋出日期:2015-08-19