Redis研究(十二)—主從複製,redis研究主從複製

來源:互聯網
上載者:User

Redis研究(十二)—主從複製,redis研究主從複製

在上一節中我們寫了Redis的資料持久化

http://blog.csdn.net/wtyvhreal/article/details/42916503


     通過持久化功能,Redis保證了即使在伺服器重啟的情況下也不會損失(或少量損失)資料。但是由於資料是儲存在一台伺服器上的,如果這台伺服器的硬碟出現故障,也會導致資料丟失。為了避免單點故障,我們希望將資料庫複寫多個副本以部署在不同的伺服器上,即使有一台伺服器出現故障其他伺服器依然可以繼續提供服務。這就要求當一台伺服器上的資料庫更新後,可以自動將更新的資料同步到其他伺服器上,Redis提供了複製(replication )功能可以自動實現同步的過程。


1.配置

同步後的資料庫分為兩類,一類是主要資料庫(master),一類是從資料庫(slave)。主要資料庫可以進行讀寫操作,當發生寫操作時自動將資料同步給從資料庫。而從資料庫一般是唯讀,並接受主要資料庫同步過來的資料。一個主要資料庫可以擁有多個從資料庫,而一個從資料庫只能擁有一個主要資料庫。

在Redis中使用複製功能非常容易,只需要在從資料庫的設定檔中加入“slaveof主要資料庫IP主要資料庫連接埠”即可,主要資料庫無需進行任何配置。為了能夠更直觀地展示複製的流程,下面將進行簡單的示範。我們要在一台伺服器上啟動兩個Redis執行個體,監聽不同連接埠,其中一個作為主要資料庫,另一個作為從資料庫。首先我們不加任何參數來啟動一個Redis執行個體作為主要資料庫:

redis-server

該執行個體預設監聽6379連接埠。然後加上slaveof參數啟動另一個Redis執行個體作為從資料庫,並讓其監聽6380連接埠:

redis-server --port 6380 --slaveof 127.0.0.1 6379

此時在主要資料庫中的任何資料變化都會自動同步到從資料庫中。我們開啟redis-cli執行個體A並串連到主要資料庫:

redis-cli

再開啟redis-cli執行個體B並串連到從資料庫:

redis-cli -p 6380

在執行個體A中使用SET命令設定一個鍵的值:

redis A>SET foo barOK

此時在執行個體B中就可以獲得該值了:
redis B>GET foo"bar "

但在預設情況下從資料庫是唯讀,如果直接修改從資料庫的資料會出現錯誤:

redis B>SET foo hi(error) 


可以通過設定從資料庫的設定檔中的slave-read-only 為no以使從資料庫可寫,但是對從資料庫的任何更改都不會同步給任何其他資料庫,並且一旦主要資料庫中更新了對應的資料就會覆蓋從資料庫中的改動。
配置多台從資料庫的方法也一樣,在所有的從資料庫的設定檔中都加上 slaveof參數指向同一個主要資料庫即可。
除了通過設定檔或命令列參數設定slaveof參數,還可以在運行時使用SLAVEOF命令修改:

redis>SLAVEOF  127.0.0.1 6379

如果該資料庫已經是其他主要資料庫的從資料庫了, SLAVEOF命令會停止和原來資料庫的同步轉而和新資料庫同步。還可以使用SLAVEOFNO  ONE來使當前資料庫停止接收其他資料庫的同步轉成主要資料庫。


2.原理

     當一個從資料庫啟動後,會向主要資料庫發送SYNC命令,主要資料庫接收到SYNC命令後會開始在後台儲存快照(即RDB持久化的過程),並將儲存期間接收到的命令緩衝起來。當快照完成後,Redi s會將快照檔案和所有緩衝的命令發送給從資料庫。從資料庫收到後,會載入快照檔案並執行收到的緩衝的命令。當主從資料庫斷開重連後會重新執行上述操作,不支援斷點續傳。
     實際的過程略微複雜一些,由於Redi s伺服器使用TCP協議通訊,所以我們可以使用telnet工具偽裝成一個從資料庫來瞭解同步的具體過程。首先在命令列中串連主要資料庫(預設連接埠為6379,且沒有任何從資料庫連接):

telnet 127.0.0.1 6379Trying 127.0.0.1...Connected  to localhost.Escape  chaacter  is '^]' .

然後作為從資料庫,我們先要發送PING命令確認主要資料庫是否可以串連:
PING+PONG

主要資料庫會回複+PONG。如果沒有收到主要資料庫的回複,則向使用者提示錯誤。如果主要資料庫要求輸入密碼才能串連,我們還得發送AUTH命令進行驗證。而後向主要資料庫發送REPLCONF命令說明自己的連接埠號碼(這裡隨便選擇了一個):
REPLCONF  listening-port 6381+OK

這時就可以開始同步的過程了:向主要資料庫發送SYNC命令開始同步,此時主要資料庫發送回快照檔案和緩衝的命令。目前主要資料庫中只有一個foo鍵,所以收到的內容如下(快照檔案是二進位格式,從第三行開始):
SYNC29REDI S0006?foobar ?6_?"

      從資料庫會將收到的內容寫入到硬碟上的臨時檔案中,當寫入完成後從資料庫會用該臨時檔案替換RDB快照檔案(RDB快照檔案的位置就是持久化時配置的位置,由dir和dbfilename兩個參數確定),之後的操作就和RDB持久化時啟動恢複的過程一樣了。需要注意的是在同步的過程中從資料庫並不會阻塞,而是可以繼續處理用戶端發來的命令。預設情況下,從資料庫會用同步前的資料對命令進行響應。可以配置slave-serve-stale-data參數為no來使從資料庫在同步完成前對所有命令(除了INFO和SLAVEOF)都回複錯誤:“SYNC with  master in  progress.”
      之後主要資料庫的任何資料變化都會同步給從資料庫,同步的內容和Redis通訊協定一樣,比如我們在主要資料庫中執行SET foo hi,通過telnet我們收到了:
*3$3set$3foo$2hi

       在複製的過程中,快照無論在主要資料庫還是從資料庫中都起了很大的作用,只要執行複製就會進行快照,即使我們關閉了RDB方式的持久化(通過刪除所有save參數)。更進一步,無論是否啟用了RDB方式的持久化,Redis在啟動時都會嘗試讀取dir和dbfilename兩個參數指定的RDB檔案來恢複資料庫。


3.圖結構

從資料庫不僅可以接收主要資料庫的同步資料,自己也可以同時作為主要資料庫存在,形成類似圖的結構,,資料庫A的資料會同步到B和C中,而B中的資料會同步到D和E中。向B中寫入資料不會同步到A或C中,只會同步到D和E中,


4.讀寫分離

    通過複製可以實現讀寫分離以提高伺服器的負載能力。在常見的情境中,讀的頻率大於寫,當單機的Redis無法應付大量的讀請求時(尤其是較耗資源的請求,比如SORT命令等)可以通過複製功能建立多個從資料庫,主要資料庫只進行寫操作,而從資料庫負責讀操作。


5.從資料庫持久化

    另一個相對耗時的操作是持久化,為了提高效能,可以通過複製功能建立一個(或若干個)從資料庫,並在從資料庫中啟用持久化,同時在主要資料庫禁用持久化。當從資料庫崩潰時重啟後主要資料庫會自動將資料同步過來,所以無需擔心資料丟失。而當主要資料庫崩潰時,需要在從資料庫中使用SLAVEOF NO ONE命令將從資料庫提升成主要資料庫繼續服務,並在原來的主要資料庫啟動後使用SLAVEOF命令將其設定成新的主要資料庫的從資料庫,即可將資料同步回來。





相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.