詳談Redis主從複製原理

迷倪小魏發表於2018-06-17


在前面的一篇部落格中【Redis多例項及主從複製環境搭建】簡單的介紹了一下redis的主從複製原理以及搭建redis的主從複製環境,


      Redis的複製是基於rdb方式的持久化實現的,即主資料庫端在後臺儲存rdb快照,從資料庫端則接受並載入快照檔案、這樣的實現優點是可以顯著的簡化邏輯,複用已有的程式碼,但是缺點也是非常明顯的:

(1)當主資料庫禁用rdb快照時[刪除配置檔案中的save語句],如果執行了複製初始化的操作,redis依然會生成rdb快照,所以下次啟動後主資料庫會以該快照恢復資料。因為複製發生的時間不能確定,這使得恢復資料可能是任何的時間點的。

(2)因為複製初始化的時候需要在硬碟中建立rdb快照檔案,所以如果硬碟的效能很慢時,這一過程會對效能產生影響。舉個例子來說,當使用redis做快取系統時,因為可能不需要持久化,所以伺服器的硬碟讀寫速度可能較差。但是當該快取系統使用一主多從的架構時,每次和從資料庫與同步,redis都會執行一次快照,同時對硬碟進行讀寫,導致效能降低。

因此,從redis2.8.18版本開始,redis引入了無硬碟複製選項,開啟該選項時,redis在與從資料庫進行復制初始化時將不會將快照內容儲存到硬碟上,而是直接透過網路的傳送給資料庫,有效的避免了效能的瓶頸問題。

可以在配置檔案中使用如下的引數配置來開啟該功能:

repl-diskless-sync yes

 

一、全量複製

全量複製的過程:

1、從伺服器向主伺服器傳送PSYNC命令,攜帶主伺服器的runid和複製偏移量;第一次的話,slave不知道master 的 runid,所以是?,偏移量是-1

2、主伺服器驗證runid和自身runid是否一致,如不一致,則進行全量複製;

3、Master把自己的runid和offset(偏移量)發給slave

4、Slave將master的runid和offset進行儲存

5、Master進行bgsave,生成RDB檔案

6、在生成RDB檔案的過程中,如果master再有寫操作,會將寫操作放入repl_back_buffer緩衝區

7、將寫好的RDB檔案傳遞給slave,將緩衝區內的資料傳送給slave

8、Salve清楚原來的資料,載入RDB和緩衝區資料

 

全量複製的開銷包括以下幾個方面:

1、bgsave時間

2、RDB檔案網路傳輸時間

3、從節點清空資料時間

4、從節點載入RDB資料時間


 

二、增量複製

 

接下來重點說一下增量複製,瞭解了全量複製後,我們會出現這樣的一個疑問:

當主從資料庫連線斷開後,從資料庫會傳送SYNC命令來重新進行一次完整複製操作。【提示:redis 2.8版本之後從資料庫會向主資料庫傳送PSYNC命令來代替SYNC以實現增量複製】這樣即使主從斷開期間資料庫的變化很小,甚至沒有,也需要將資料庫中的所有資料重新快照並傳送一次。在正常的網路應用環境中,這種實現方式顯然不是很理想。Redis 2.8版本的重要更新之一就是主從斷線重連的情況下的增量複製。

 

增量複製是基於下面三點實現的:

(1)從資料庫會儲存主資料庫的執行id[run id]。每一個redis例項執行都會有一個唯一的執行id,每當例項重新啟動後,就會重新生成一個新的執行id。

(2)在複製同步階段,主資料庫每將一個命令傳送給從資料庫時,都會同時把該命令存放在一個積壓佇列中(backlog),並記錄下當前積壓佇列中存放命令的的偏移量。

(3)同時,從資料庫接受到主資料庫傳來的命令時,會影響該命令的偏移量。

以上的3點是實現增量複製的基礎。如上所述,當主從連線準備就緒後,從資料庫會傳送一條SYNC命令來告訴主資料庫可以開始把所有資料同步過來,而2.8版本後,不在傳送SYNC命令,取而代之的是PSYNC,格式為“PSYNC 主資料庫的執行id 斷開前最新的命令偏移量”。當主資料庫收到PSYNC命令後,會執行以下的判斷來決定此次重連是否可以執行增量複製:

(1)首先,主資料庫會判斷從資料庫傳來的執行id是否和自己的執行id相同、這一步驟的意義在於確保從資料庫之前確實是和自己同步的,以避免從資料庫拿到錯誤的資料[比如主資料庫在斷開期間重啟過,會造成資料的不一致]。

(2)然後判斷從資料庫最後同步成功的命令的偏移量是否在積壓佇列中,如果在則可以執行增量複製,並將積壓佇列中的相應的命令傳送給從資料庫。如果此次重連不滿足增量複製的條件,主資料庫會進行一次全部同步。

 

下面簡單的解釋一下什麼是積壓佇列:

積壓佇列在本質上是一個固定長度的迴圈佇列,預設情況下積壓佇列的大小為1M,可以透過配置檔案中的repl-backlog-size引數來調整大小。很容易理解的是,積壓佇列越大,其允許的主從資料庫斷線的時間就越長。根據主從資料庫之間的網路狀態,設定一個合理的積壓佇列很重要。因為積壓佇列儲存的的內容是命令本身,如:set name wjq,所以估算積壓佇列的大小隻需要估計主從資料庫斷線的時間中主資料庫可能執行的命令大小即可。

與積壓佇列相關的另一個配置選項使repl-backlog-ttl,即當所有從資料庫與主資料庫斷開連線後,經過多久時間可以釋放積壓佇列的記憶體空間。預設是1小時[3600s];

 

 

 

我們可以看到主節點記錄了從節點的偏移量資訊。


 
關於redis主從複製環境搭建可參考:Redis多例項及主從複製環境搭建http://blog.itpub.net/31015730/viewspace-2155578/

下面配置檔案redis.conf中關於主從複製的一些配置引數進行了解釋說明:


關於redis配置檔案的引數介紹可參考:redis配置檔案中各引數詳解http://blog.itpub.net/31015730/viewspace-2154818/

################################# REPLICATION #################################

# 將當前節點設定為執行在機器127.0.0.1上的6379埠例項的從節點  

# slaveof <masterip> <masterport>  

slaveof 127.0.0.1 6379  

  

# 主節點設定驗證密碼,從節點在進行復制請求時,需要透過auth進行驗證  

# masterauth <master-password>  

masterauth qcloud@2018  

  

# 從節點和主節點失去連線或者從節點正處於複製資料過程中,從節點響應客戶端的方式  

# “yes” 從節點使用舊資料響應客戶端請求  

no從節點給客戶端反饋一個錯誤資訊"SYNC with master in progress"  

slave-serve-stale-data yes  

  

# 從Redis 2.6開始 從節點預設只讀模式。有時可以將從節點配置為可寫模式,但是隻能儲存臨時的資料,因為主從同步會很快刪除這些臨時資料。  

# 同時注意從節點不能暴露給不安全的網路環境下  

slave-read-only yes  

  

  

# 從機器會每隔10秒鐘 向主傳送ping命令 以保住主節點活著  

# repl-ping-slave-period 10  

  

# 這是個響應超時的時間,需要從兩個角度來看  

# 從的角度來看,批次傳輸資料、從ping主等  

# 主的角度來看,REPLCONF ACK pings等   

# 這個值一定要大於repl-ping-slave-period 這個值  

# repl-timeout 60  

  

  

# 若配置為yes,則禁用NO_DELAY,則TCP協議棧會合並小包統一傳送,這樣可以減少主從節點間的包數量並節省頻寬,但會增加資料同步到slave的時間。  

# 若配置為no,表明啟用NO_DELAY,則TCP協議棧不會延遲小包的傳送時機,這樣資料同步的延時會減少,但需要更大的頻寬。  

# 通常情況下,應該配置為no以降低同步延時,但在主從節點間網路負載已經很高的情況下,可以配置為yes。  

repl-disable-tcp-nodelay no  

  

  

# 主節點的複製緩衝區大小,預設是1M,根據實際情況可以調大這個數值  

# repl-backlog-size 1mb  

  

# 當主失去所有從節點時,預設經過3600秒回釋放複製緩衝區中的值  

# 當設定為0時,意味著從不釋放  

# repl-backlog-ttl 3600  

  

#Redis哨兵Sentinel會根據slave的優先順序選舉一個master。最低的優先順序的slave,當選master。  

#而配置成0,永遠不會被選舉。預設為100  

slave-priority 100  

  

#表示只有當3個(或以上)的從庫連線到主庫時,主庫才是可寫的,否則會返回錯誤  

# min-slaves-to-write 3  

 

#表示允許從庫最長失去連線的時間,如果從庫最後與主庫聯絡(即傳送“replconf  ack”命令)的時間小於這個值,則認為從庫還在保持與主庫的連線。  

# min-slaves-max-lag 10  

 

 

 更多關於redis的相關知識可參考:http://blog.itpub.net/31015730/cid-185228-list-1/


Redis 4.0叢集環境部署http://blog.itpub.net/31015730/viewspace-2155989/




作者:SEian.G(苦練七十二變,笑對八十一難)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31015730/viewspace-2156282/,如需轉載,請註明出處,否則將追究法律責任。

相關文章