Redis的主從複製

前言

  關係數據庫通常會使用一個主服務器向多個從服務器發送更新,並使用從服務器來處理所有的讀請求,Redis採用了同樣方法來實現自己的複製特性。

  簡單總結起來就是:在接收到主服務器發送的數據初始副本之後,客戶端每次主服務器進行寫命令時,從服務器都會實時地得到更新。部署好主從服務器之後,客戶端可以向任意的從服務器發送讀請求。

  本文主要介紹Redis實現數據同步複製簡單過程、新舊版本之間的對比、以及一些需要注意的細節,主要參考資料《Redis實戰》與《Redis設計與實現》(有需要的同學可以私信或者評論)

 

一、舊版複製功能

  Redis 2.8以前採用的複製都爲舊版複製,主要使用SYNC命令同步複製,SYNC存在很大的缺陷嚴重消耗主服務器的資源以及大量的網絡連接資源。Redis 2.8之後採用PSYNC命令替代SYNC,解決完善這些缺陷,但在介紹新版複製功能之前,必須先介紹舊版複製過程,這樣才能更好地形成對比。

  1、複製功能的兩種模式

    同時複製過程分爲同步sync與命令傳播(command propagate),兩個過程配合執行才能實現Redis複製。

    1)同步操作:

    通過從服務器發送到SYNC命令給主服務器-------->主服務器生成RDB文件併發送給從服務器,同時發送保存所有寫命令給從服務器------>從服務器清空之前數據並執行解釋RDB文件------->保持數據一致(還需要命令傳播過程才能保持一致)

                  

         2)命令傳播操作

    主服務器的數據庫狀態被修改(主服務器執行寫命令,修改數據庫),導致主從服務器數據庫不一致時,通過發送讓主從服務器不一致的命令(主服務器接收到的新寫命令)給從服務器並執行,讓主從服務器的數據庫重新回到一致狀態。

    比如初次同步完成後,主從服務器數據庫中都已經存在k1-k5的鍵,處於數據一致的狀態

            

    之後,主服務器客戶端發送DEL刪除命令,刪除k3鍵,導致主從服務器數據不一致

 

        

    爲了讓主從服務器數據再次回到一致狀態,主服務器向從服務器發送DEL命令,緊接着從服務器接收並執行。即可回到一致狀態

            

 

      

  2、配置選項前提

 

    1)主從複製的前提不用多說,就是先正確配置redis主從服務器,主要通過slaveof ip port選項配置或者SLAVEOF 命令。

    2)保證主服務器的RDB+AOF配置正確,特別是RDB中dbfilename選項與AOF中的dir選項,兩個文件路徑對於Redis是可寫的

 

  3、主從複製過程

              

    文字簡單總結描述:

      1)slave會建立和master的連接,然後發送sync命令;

    2)master都會啓動一個後臺進程執行BGSAVE命令,將數據快快照保存到文件中,同時master主進程會開始收集新的寫命令並緩存起來;

    3)後臺進程完成寫文件後,master發送文件給slave,slave將文件保存到磁盤上,然後加載到內存恢復數據庫快照到slave上。

    4)緊接着master就會把緩存命令轉發給slave,後續的master收到的寫命令也通過跟slave連接發送給slave;

              5)如果master同時接收到多個slave發來的同步連接請求,只會啓動一個進程來寫數據庫鏡像,然後發送給所有slave。

    也可以參考以下表,其中步驟1-4可以認爲是sync同步操作,而步驟5即爲命令傳播模式  

    

        

  注意事項

    1)從服務器在同步時,會清空所有數據,服務器在與主服務器進行初連接時,數據庫中的所有數據都將丟失,替換成主服務器發送的數據。

    2)Redis不支持主主複製

    3)主從複製不會阻塞master(不會阻塞master處理客戶端請求),相反slave在初次同步數據時會阻塞不能處理客戶端請求。

    4)當多個從服務器嘗試連接同一個主服務器的時候,就會出現以下兩種情況:

                  一是:步驟3還未執行,所有從服務器都會接收到相同的快照文件和相同緩衝區寫命令。

                  二是:步驟3正在執行或者已經執行完畢,當主服務器與較早的從服務器完成以上全部步驟之後,主服務器會新連接的從服務器重新依次執行1-5步驟。

                 在大部分情況下,Redis會儘可能去減少複製所需要的工作,但是從服務器連接的時機不湊巧的話,只好多做一些外額外工作。

    5)多個從服務器連接主服務器時候,同步數據可能會佔用很大一部分的帶寬,可能會導致其他請求難以到達主服務器。

 

  4、SYNC命令的缺陷

    主要是主從服務器斷線後重複製,即處於命令傳播階段的主從服務器由於網絡斷開,從服務器一直嘗試連接主服務器連接成功後,繼續複製主服務器。如下過程在主從服務器斷開後重新連接期間,主服務器繼續執行三個SET命令,導致從服務器連接後發送L SYNC命令,重新進行了“全量”複製過程,RDB文件中包含k1-k10089全部的鍵。

         

 

    其中可以明顯看出重新連接主服務器之後,SYNC命令創建包含k1-k10089的RDB文件。而事實上只需要再同步斷線後的k10087-k10089即可。SYNC的“全同步”對於從服務來說是不必要的。

               SYNC命令非常消耗資源,原因有三點:

    1)主服務器執行BGSAVE命令生成RDB文件,這個生成過程會大量消耗主服務器資源(CPU、內存和磁盤I/O資源)

    2)主服務器需要將自己生成的RBD發送給從從服務器,這個發送操作會消耗主從服務器大量的網絡資源(帶寬與流量)

    3)接收到RDB文件你的從服務器需要載入RDB文件,載入期間從服務器會因爲阻塞而導致沒辦法處理命令請求。

    

二、新版複製功能

  爲了解決舊版本中斷線情況下SYNC低效問題,在Redis 2.8之後使用PSYNC命令代替SYNC命令執行復制同步操作,自然PSYNC具備完整重同步和部分重同步模式

       1)完整重同步:跟舊版複製基本是一致的,可以理解爲“全量”複製。

       2)部分重同步:在命令傳播階段,斷線重複制只需要發送主服務器在斷開期間執行的寫命給從服務器即可,可以理解爲“增量”複製。

  斷開連接後發送+CONTINUE回覆,表示使用PSYNC部分重同步,只需要同步k10087-10089即可,不需要生成RDB文件

        

  相關流程圖如下:

          

 

 

 

 

 

 

 

 

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章