Redis 哨兵機制

Luson發表於2021-10-11

Redis 哨兵機制

原理

Redis Sentinel 是一個分散式架構,其中包含若干個 Sentinel 節點和 Redis 資料節點,每個 Sentinel 節點會對資料節點和其餘 Sentinel 節點進行監控,當它發現節點不可達時,會對節點做下線標識。如果被標識的是主節點,它還會和其他 Sentinel 節點進行“協商”,當大多數 Sentinel 節點都認為主節點不可達時,它們會選舉出一個 Sentinel 節點來完成自動故障轉移的工作,同時會將這個變化實時通知給 Redis 應用方。整個過程完全是自動的,不需要人工來介入,所以這套方案很有效地解決了 Redis 的高可用問題

Redis 哨兵機制

基本的故障轉移流程:

  1. 主節點出現故障,此時從節點失去連線,主從複製失敗。
  2. 每個 Sentinel 節點通過定期監控發現主節點出現了故障

Redis 哨兵機制

  1. 多個 sentinel 節點對主節點的故障達成一致選舉出其中一個節點作為領導者負責故障轉移

Redis 哨兵機制

  1. Sentinel 領導者節點執行了故障轉移,整個過程基本是跟我們手動調整一致的,只不過是自動化完成的

Redis 哨兵機制

  1. 故障轉移後整個 Redis Sentinel 的結構,重新選舉了新的主節點。
    Redis 哨兵機制

Redis Sentinel 具有以下幾個功能:

  • 監控:Sentinel 節點會定期檢查 Redis 資料節點、其餘 Sentinel 節點是否可達

  • 通知:Sentinel 節點會將故障轉移的結果通知給應用方

  • 主節點故障轉移:實現從節點晉升為主節點並維護後續正確的主從關係

  • 配置提供者: 在Redis Sential 結構中,客戶端在初始化的時候連線的是 Sentinel 節點集合,從中獲取主節點的資訊
    同時Redis Sentinel 包含了若個 Sentinel 節點,這樣做也帶來了兩個好處:

    • 對於節點的故障判斷是由多個 Sentinel 節點共同完成,這樣可以有效地防止誤判
    • Sentinel 節點集合是由若干個 Sentinel 節點組成的,這樣即使個別 Sentinel 節點不可用,整個 Sentinel 節點集合依然是健壯的,但是 Sentinel 節點本身就是獨立的 Redis 節點,只不過它們有一些特殊,它們不儲存資料,只支援部分命令

    Sentinel 的核心配置

Redis 哨兵機制

docker run -itd  --name  redis-slave2  --net mynetwork  -p 6381:6379  --ip 172.10.0.3  redis2 

 docker run -itd  --name  redis-slave3  --net mynetwork  -p 6382:6379  --ip 172.10.0.4  redis2 


 docker run -itd  --name  redis-sentinel1  --net mynetwork  -p 22530:26379  --ip 172.10.0.9  redis2 

 docker run -itd  --name  redis-sentinel2  --net mynetwork  -p 22531:26379  --ip 172.10.0.10   redis2 

 docker run -itd  --name  redis-sentinel3  --net mynetwork  -p 22532:26379  --ip 172.10.0.11   redis2

sentinel monitor mymaster 127.0.0.1 7000 2

監控的主節點的名字、IP 和埠,最後一個2的意思是有幾臺 Sentinel 發現有問題,就會發生故障轉移,例如 配置為2,代表至少有2個 Sentinel 節點認為主節點不可達,那麼這個不可達的判定才是客觀的。對於設定的越小,那麼達到下線的條件越寬鬆,反之越嚴格。一般建議將其設定為 Sentinel 節點的一半加1

sentinel down-after-millseconds mymaster 30000

這個是超時的時間(單位為毫秒)。打個比方,當你去 ping 一個機器的時候,多長時間後仍 ping 不通,那麼就認為它是有問題

sentinel parallel-syncs mymaster 1

當 Sentinel 節點集合對主節點故障判定達成一致時,Sentinel 領導者節點會做故障轉移操作,選出新的主節點,原來的從節點會向新的主節點發起復制操作,parallel-syncs 就是用來限制在一次故障轉移之後,每次向新的主節點發起復制操作的從節點個數,指出 Sentinel 屬於併發還是序列。1代表每次只能複製一個,可以減輕 Master 的壓力;

Redis 哨兵機制

sentinel auth-pass master-name password

如果 Sentinel 監控的主節點配置了密碼,sentinel auth-pass 配置通過新增主節點的密碼,防止 Sentinel 節點對主節點無法監控。

sentinel failover-timeout mymaster 180000
表示故障轉移的時間

sentinel支援的合法命令如下:
SENTINEL masters 顯示被監控的所有master以及它們的狀態.

SENTINEL master <master name> 顯示指定master的資訊和狀態;

SENTINEL slaves <master name> 顯示指定master的所有slave以及它們的狀態;

SENTINEL get-master-addr-by-name <master name> 返回指定master的ip和埠,如果正在進行failover或者failover已經完成,將會顯示被提升為master的slave的ip和埠。

SENTINEL failover <master name> 強制sentinel執行failover,並且不需要得到其他sentinel的同意。但是failover後會將最新的配置傳送給其他sentinel。

實現

Sentinel 的實現原理,主要分為以下幾個步驟:

  1. 檢測問題,主要講的是三個定時任務,這三個內部的執行任務可以保證出現問題馬上讓 Sentinel 知道。

  2. 發現問題,主要講的是主觀下線和客觀下線。當有一臺 Sentinel 機器發現問題時,它就會主觀對它主觀下線,但是當多個 Sentinel 都發現有問題的時候,才會出現客觀下線。

  3. 找到解決問題的人,主要講的是領導者選舉,如何在 Sentinel 內部多臺節點做領導者選舉,選出一個領導者。

  4. 解決問題,主要講的是故障轉移,即如何進行故障轉移

問題檢測
Sentinel 會執行以下三個定時任務
每10秒每個 Sentinel 對 Master 和 Slave 執行一次 Info Replication。

每2秒每個 Sentinel 通過 Master 節點的 channel 交換資訊(pub/sub)。

每1秒每個 Sentinel 對其他 Sentinel 和 Redis 執行 ping

第一個定時任務,指的是 Redis Sentinel 可以對 Redis 節點做失敗判斷和故障轉移,在 Redis 內部有三個定時任務作為基礎,來 Info Replication 發現 Slave 節點,這個命令可以確定主從關係。
第兩個定時任務,類似於釋出訂閱,Sentinel 會對主從關係進行判定,通過 sentinel:hello 頻道互動。瞭解主從關係可以幫助更好的自動化操作 Redis。然後 Sentinel 會告知系統訊息給其它 Sentinel 節點,最終達到共識,同時 Sentinel 節點能夠互相感知到對方。

第三個定時任務,指的是對每個節點和其它 Sentinel 進行心跳檢測,它是失敗判定的依據。

主觀下線和客觀下線
Sentinel 會 ping 每個節點,如果超過30秒,依然沒有回覆的話,做下線的判斷。
每個 Sentinel 節點對 Redis 節點失敗的“偏見”。之所以是偏見,只是因為某一臺機器30秒內沒有得到回覆;
這個時候需要所有 Sentinel 節點都發現它30秒內無回覆,才會達到共識。
領導者選舉方式
1.每個做主觀下線的sentinel節點,會向其他的sentinel節點傳送命令,要求將它設定成為領導者

2.收到命令sentinel節點,如果沒有同意通過其它節點傳送的命令,那麼就會同意請求,否則就會拒絕

3.如果sentinel節點發現自己票數超過半數,同時也超過了sentinel monitor mymaster 127.0.0.1 6379 2 超過2個的時候,就會成為領導者

4.進行故障轉移操作
如何選擇“合適的”Slave 節點
Redis 內部其實是有一個優先順序配置的,在配置檔案中 slave-priority,這個引數是 Salve 節點的優先順序配置,如果存在則返回,如果不存在則繼續。
當上面這個優先順序不滿足的時候,Redis 還會選擇複製偏移量最大的 Slave節點,如果存在則返回,如果不存在則繼續。之所以選擇偏移量最大,這是因為偏移量越小,和 Master 的資料越不接近,現在 Master掛掉了,說明這個偏移量小的機器資料也可能存在問題,這就是為什麼要選偏移量最大的 Slave 的原因。
如果發現偏移量都一樣,這個時候 Redis 會預設選擇 runid 最小的節點

生產環境中部署技巧

  1. Sentinel 節點不應該部署在一臺物理“機器”上。
  2. 部署至少三個且奇數個的 Sentinel 節點
    3個以上是通過增加 Sentinel 節點的個數提高對於故障判定的準確性,因為領導者選舉需要至少一半加1個節點,奇數個節點可以在滿足該條件的基礎上節省一個節點

常見問題

  1. 非同步複製導致資料丟失
    因為master->slave的複製是非同步,所以可能有部分還沒來得及複製到slave就當機了,此時這些部分資料就丟失了。
  2. 叢集腦裂導致資料丟失
    腦裂,也就是說,某個master所在機器突然脫離了正常的網路,跟其它slave機器不能連線,但是實際上master還執行著。
    造成的問題:
    此時哨兵可能就會認為master當機了,然後開始選舉,講其它slave切換成master。這時候叢集裡就會有2個master,也就是所謂的腦裂。
    此時雖然某個slave被切換成了master,但是可能client還沒來得及切換成新的master,還繼續寫向舊的master的資料可能就丟失了。
    因此舊master再次恢復的時候,會被作為一個slave掛到新的master上去,自己的資料會被清空,重新從新的master複製資料

解決

min-slaves-to-write 1
min-slaves-max-lag  10

要求至少有1個slave,資料複製和同步的延遲不能超過10秒
如果說一旦所有的slave,資料複製和同步的延遲都超過了10秒鐘,那麼這個時候,master就不會再接收任何請求了
上面兩個配置可以減少非同步複製和腦裂導致的資料丟失

參考文獻 redis.cn/topics/sentinel.html

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章