1. 程式人生 > >Redis多機資料庫

Redis多機資料庫

複製

PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)兩種模式:

·其中完整重同步用於處理初次複製情況:完整重同步的執行步驟和SYNC命令的執行步驟基本一樣,它們都是通過讓主伺服器建立併發送RDB檔案,以及向從伺服器傳送儲存在緩衝區裡面的寫命令來進行同步。

·部分重同步則用於處理斷線後重複製情況:當從伺服器在斷線後重新連線主伺服器時,如果條件允許,主伺服器可以將主從伺服器連線斷開期間執行的寫命令傳送給從伺服器,從伺服器只要接收並執行這些寫命令,就可以將資料庫更新至主伺服器當前所處的狀態。

Redis為複製積壓緩衝區設定的預設大小為1MB,如果主伺服器需要執行大量寫命令,又或者主從伺服器斷線後重連線所需的時間比較長,那麼這個大小也許並不合適。如果複製積壓緩衝區的大小設定得不恰當,那麼PSYNC命令的複製重同步模式就不能正常發揮作用,因此,正確估算和設定複製積壓緩衝區的大小非常重要。

 

 

如果從伺服器儲存的執行ID和當前連線的主伺服器的執行ID並不相同,那麼說明從伺服器斷線之前複製的主伺服器並不是當前連線的這個主伺服器,主伺服器將對從伺服器執行完整重同步操作。

 

 

·部分重同步通過複製偏移量、複製積壓緩衝區、伺服器執行ID三個部分來實現。

·在複製操作剛開始的時候,從伺服器會成為主伺服器的客戶端,並通過向主伺服器傳送命令請求來執行復制步驟,而在複製操作的後期,主從伺服器會互相成為對方的客戶端。

·主伺服器通過向從伺服器傳播命令來更新從伺服器的狀態,保持主從伺服器一致,而從伺服器則通過向主伺服器傳送命令來進行心跳檢測,以及命令丟失檢測。

 

Sentinel

因為Sentinel本質上只是一個執行在特殊模式下的Redis伺服器,所以啟動Sentinel的第一步,就是初始化一個普通的Redis伺服器。因為Sentinel執行的工作和普通Redis伺服器執行的工作不同,所以Sentinel的初始化過程和普通Redis伺服器的初始化過程並不完全相同。

 

 

 

 

 

 

 

Sentinel除了會為這個新的從伺服器建立相應的例項結構之外,Sentinel還會建立連線到從伺服器的命令連線和訂閱連線。

 

對於每個與Sentinel連線的伺服器,Sentinel既通過命令連線向伺服器的__sentinel__:hello頻道傳送資訊,又通過訂閱連線從伺服器的__sentinel__:hello頻道接收資訊

 

對於監視同一個伺服器的多個Sentinel來說,一個Sentinel傳送的資訊會被其他Sentinel接收到,這些資訊會被用於更新其他Sentinel對傳送資訊Sentinel的認知,也會被用於更新其他Sentinel對被監視伺服器的認知。

 

主伺服器例項結構中的sentinels字典

 

當Sentinel通過頻道資訊發現一個新的Sentinel時,它不僅會為新Sentinel在sentinels字典中建立相應的例項結構,還會建立一個連向新Sentinel的命令連線,而新Sentinel也同樣會建立連向這個Sentinel的命令連線,最終監視同一主伺服器的多個Sentinel將形成相互連線的網路:Sentinel A有連向Sentinel B的命令連線,而Sentinel B也有連向Sentinel A的命令連線。

 

檢查主觀下線

在預設情況下,Sentinel會以每秒一次的頻率向所有與它建立了命令連線的例項(包括主伺服器、從伺服器、其他Sentinel在內)傳送PING命令,並通過例項返回的PING命令回覆來判斷例項是否線上。

帶箭頭的連線顯示了Sentinel1和Sentinel2是如何向例項傳送PING命令的:

·Sentinel1將向Sentinel2、主伺服器master、從伺服器slave1和slave2傳送PING命令。

·Sentinel2將向Sentinel1、主伺服器master、從伺服器slave1和slave2傳送PING命令。

例項對PING命令的回覆可以分為以下兩種情況:

·有效回覆:例項返回+PONG、-LOADING、-MASTERDOWN三種回覆的其中一種。

·無效回覆:例項返回除+PONG、-LOADING、-MASTERDOWN三種回覆之外的其他回覆,或者在指定時限內沒有返回任何回覆。

Sentinel配置檔案中的down-after-milliseconds選項指定了Sentinel判斷例項進入主觀下線所需的時間長度:如果一個例項在down-after-milliseconds毫秒內,連續向Sentinel返回無效回覆,那麼Sentinel會修改這個例項所對應的例項結構,在結構的flags屬性中開啟SRI_S_DOWN標識,以此來表示這個例項已經進入主觀下線狀態。

down-after-milliseconds選項另一個需要注意的地方是,對於監視同一個主伺服器的多個Sentinel來說,這些Sentinel所設定的down-after-milliseconds選項的值也可能不同,因此,當一個Sentinel將主伺服器判斷為主觀下線時,其他Sentinel可能仍然會認為主伺服器處於線上狀態。

 

檢查客觀下線

當Sentinel將一個主伺服器判斷為主觀下線之後,為了確認這個主伺服器是否真的下線了,它會向同樣監視這一主伺服器的其他Sentinel進行詢問,看它們是否也認為主伺服器已經進入了下線狀態(可以是主觀下線或者客觀下線)。當Sentinel從其他Sentinel那裡接收到足夠數量的已下線判斷之後,Sentinel就會將從伺服器判定為客觀下線,並對主伺服器執行故障轉移操作。

根據其他Sentinel發回的SENTINEL is-master-down-by-addr命令回覆,Sentinel將統計其他Sentinel同意主伺服器已下線的數量,當這一數量達到配置指定的判斷客觀下線所需的數量時,Sentinel會將主伺服器例項結構flags屬性的SRI_O_DOWN標識開啟,表示主伺服器已經進入客觀下線狀態。

當認為主伺服器已經進入下線狀態的Sentinel的數量,超過Sentinel配置中設定的quorum引數的值,那麼該Sentinel就會認為主伺服器已經進入客觀下線狀態。

sentinel monitor master 127.0.0.1 6379 5

包括當前Sentinel在內,總共要有五個Sentinel都認為主伺服器已經下線,當前Sentinel才會將主伺服器判斷為客觀下線。

對於監視同一個主伺服器的多個Sentinel來說,它們將主伺服器標判斷為客觀下線的條件可能也不同:當一個Sentinel將主伺服器判斷為客觀下線時,其他Sentinel可能並不是那麼認為的。

 

選舉領頭 Sentinel

當一個主伺服器被判斷為客觀下線時,監視這個下線主伺服器的各個Sentinel會進行協商,選舉出一個領頭Sentinel,並由領頭Sentinel對下線主伺服器執行故障轉移操作。

和檢測客觀下線狀態時傳送的SENTINEL is-master-down-by-addr命令不同,Sentinel這次傳送的命令會帶有Sentinel自己的執行ID

 

SENTINEL is-master-down-by-addr 127.0.0.1 6379 0 e955b4c85598ef5b5f055bc7ebfd5e828dbed4fa

如果接收到這個命令的Sentinel還沒有設定區域性領頭Sentinel的話,它就會將執行ID為e955b4c85598ef5b5f055bc7ebfd5e828dbed4fa的Sentinel設定為自己的區域性領頭Sentinel

接收到命令回覆的Sentinel就可以根據這一回復,統計出有多少個Sentinel將自己設定成了區域性領頭Sentinel。

根據命令請求傳送的先後順序不同,可能會有某個Sentinel的SENTINEL is-master-down-by-addr命令比起其他Sentinel傳送的相同命令都更快到達,並最終勝出領頭Sentinel的選舉,然後這個領頭Sentinel就可以開始對主伺服器執行故障轉移操作了。

 

故障轉移

在選舉產生出領頭Sentinel之後,領頭Sentinel將對已下線的主伺服器執行故障轉移操作,該操作包含以下三個步驟:

1)在已下線主伺服器屬下的所有從伺服器裡面,挑選出一個從伺服器,並將其轉換為主伺服器。

2)讓已下線主伺服器屬下的所有從伺服器改為複製新的主伺服器。

3)將已下線主伺服器設定為新的主伺服器的從伺服器,當這個舊的主伺服器重新上線時,它就會成為新的主伺服器的從伺服器。

 

 

 

·Sentinel只是一個執行在特殊模式下的Redis伺服器,它使用了和普通模式不同的命令表,所以Sentinel模式能夠使用的命令和普通Redis伺服器能夠使用的命令不同。

·Sentinel會讀入使用者指定的配置檔案,為每個要被監視的主伺服器建立相應的例項結構,並建立連向主伺服器的命令連線和訂閱連線,其中命令連線用於向主伺服器傳送命令請求,而訂閱連線則用於接收指定頻道的訊息。

·Sentinel通過向主伺服器傳送INFO命令來獲得主伺服器屬下所有從伺服器的地址資訊,併為這些從伺服器建立相應的例項結構,以及連向這些從伺服器的命令連線和訂閱連線。

·在一般情況下,Sentinel以每十秒一次的頻率向被監視的主伺服器和從伺服器傳送INFO命令,當主伺服器處於下線狀態,或者Sentinel正在對主伺服器進行故障轉移操作時,Sentinel向從伺服器傳送INFO命令的頻率會改為每秒一次。

·對於監視同一個主伺服器和從伺服器的多個Sentinel來說,它們會以每兩秒一次的頻率,通過向被監視伺服器的__sentinel__:hello頻道傳送訊息來向其他Sentinel宣告自己的存在。

·每個Sentinel也會從__sentinel__:hello頻道中接收其他Sentinel發來的資訊,並根據這些資訊為其他Sentinel建立相應的例項結構,以及命令連線。

·Sentinel只會與主伺服器和從伺服器建立命令連線和訂閱連線,Sentinel與Sentinel之間則只建立命令連線。

·Sentinel以每秒一次的頻率向例項(包括主伺服器、從伺服器、其他Sentinel)傳送PING命令,並根據例項對PING命令的回覆來判斷例項是否線上,當一個例項在指定的時長中連續向Sentinel傳送無效回覆時,Sentinel會將這個例項判斷為主觀下線。

·當Sentinel將一個主伺服器判斷為主觀下線時,它會向同樣監視這個主伺服器的其他Sentinel進行詢問,看它們是否同意這個主伺服器已經進入主觀下線狀態。

·當Sentinel收集到足夠多的主觀下線投票之後,它會將主伺服器判斷為客觀下線,併發起一次針對主伺服器的故障轉移操作。

 

叢集

 

 

 

引用

《Redis 設計與實現》