Redis核心技術筆記07-08

IT小馬發表於2023-01-11

哨兵機制

如果主庫掛了,我們就需要執行一個新主庫,比如說把一個從庫切換為主庫,把它當成主庫。

在 Redis 主從叢集中,哨兵機制是實現主從庫自動切換的關鍵機制,它有效地解決了主從複製模式下故障轉移的這三個問題。

基本任務

  1. 監控:主庫真的掛了嗎?
    a. 採用多例項組成的叢集模式進行部署,這也被稱為哨兵叢集。
    b. 引入多個哨兵例項一起來判斷,
  2. 選主:選擇哪個從庫作為主庫?
    a. 透過線上狀態、網路狀況篩選掉一部分從庫
    b. 再根據優先順序、複製進度、從庫的id進行打分
    c. 得分最高的就是新的主庫
  3. 通知:把新主庫的相關資訊通知給從庫和客戶端

監控

哨兵程式在執行時,週期性地給所有的主從庫傳送 PING 命令,檢測它們是否仍然線上執行。如果從庫沒有在規定時間內響應哨兵的 PING 命令,哨兵就會把它標記為“下線狀態”;
同樣,如果主庫也沒有在規定時間內響應哨兵的 PING 命令,哨兵就會判定主庫下線,然後開始自動切換主庫的流程。

選出新主庫

主庫掛了以後,哨兵就需要從很多個從庫裡,按照一定的規則選擇一個從庫例項,把它作為新的主庫。

通知

  • 哨兵會把新主庫的連線資訊發給其他從庫,讓它們執行 replicaof 命令,和新主庫建立連線,並進行資料複製。
  • 同時,哨兵會把新主庫的連線資訊通知給客戶端,讓它們把請求操作發到新主庫上。

主觀下線和客觀下線

哨兵程式會使用 PING 命令檢測它自己和主、從庫的網路連線情況,用來判斷例項的狀態。

如果哨兵發現主庫或從庫對 PING 命令的響應超時了,那麼,哨兵就會先把它標記為“主觀下線”。

  • 從庫響應超時,哨兵可以直接標記為“主觀下線”
  • 主庫需要哨兵叢集一起判斷,只有大多數的哨兵例項,都判斷主庫已經“主觀下線”了,主庫才會被標記為“客觀下線”

客觀下線標準:

  • 當有 N 個哨兵例項時,最好要有 N/2 + 1 個例項判斷主庫為“主觀下線”,才能最終判定主庫為“客觀下線”。
  • 管理員可自行設定。

重新選主

在多個從庫中,先按照一定的篩選條件,把不符合條件的從庫去掉。然後再按照一定的規則,給剩下的從庫逐個打分,將得分最高的從庫選為新主庫。

篩選條件

在選主時,除了要檢查從庫的當前線上狀態,還要判斷它之前的網路連線狀態。

判斷網路連線狀態:
down-after-milliseconds 是我們認定主從庫斷連的最大連線超時時間。
如果在 down-after-milliseconds 毫秒內,主從節點都沒有透過網路聯絡上,我們就可以認為主從節點斷連了。如果發生斷連的次數超過了 10 次,就說明這個從庫的網路狀況不好,不適合作為新主庫。

三輪打分

按照從庫優先順序、從庫複製進度以及從庫 ID 號進行打分。只要在某一輪中,有從庫得分最高,那麼它就是主庫了,選主過程到此結束。如果沒有出現得分最高的從庫,那麼就繼續進行下一輪。
  1. 優先順序:slave-priority 配置項
  2. 複製進度:slave_repl_offset 最接近 master_repl_offset
  3. ID號:ID號最小的從庫得分最高

小結

Redis 的哨兵機制自動完成了以下三大功能,從而實現了主從庫的自動切換,可以降低 Redis 叢集的運維開銷:

  • 監控主庫執行狀態,並判斷主庫是否客觀下線;
  • 在主庫客觀下線後,選取新主庫;
  • 選出新主庫後,通知從庫和客戶端。

問題:哨兵在操作主從切換的過程中,客戶端能否正常地進行請求操作?
回答:如果客戶端使用了讀寫分離,那麼讀請求可以在從庫上正常執行,不會受到影響。但是由於此時主庫已經掛了,而且哨兵還沒有選出新的主庫,所以在這期間寫請求會失敗,失敗持續的時間 = 哨兵切換主從的時間 + 客戶端感知到新主庫 的時間。

08 哨兵叢集

配置哨兵資訊

sentinel monitor <master-name> <ip> <redis-port> <quorum> 

叢集組成

哨兵例項之間可以相互發現,要歸功於 Redis 提供的 pub/sub 機制,也就是釋出 / 訂閱機制。

哨兵只要和主庫建立起了連線,就可以在主庫上釋出訊息了,比如說釋出它自己的連線資訊(IP 和埠)。同時,它也可以從主庫上訂閱訊息,獲得其他哨兵釋出的連線資訊。

Redis 會以頻道的形式,對這些訊息進行分門別類的管理。
所謂的頻道,實際上就是訊息的類別。當訊息類別相同時,它們就屬於同一個頻道。反之,就屬於不同的頻道。只有訂閱了同一個頻道的應用,才能透過釋出的訊息進行資訊交換。

哨兵互連:
在主從叢集中,主庫上有一個名為“__sentinel__:hello”的頻道,不同哨兵就是透過它來相互發現,實現互相通訊的。

哨兵連線從庫:
哨兵向主庫傳送 INFO 命令,主庫接受到這個命令後,就會把從庫列表返回給哨兵。
哨兵可以根據從庫列表中的連線資訊,和每個從庫建立連線,並在這個連線上持續地對從庫進行監控。

客戶端事件通知

哨兵是一個執行在特定模式下的 Redis 例項,它並不服務請求操作,只是完成監控、選主和通知的任務。

每個哨兵例項也提供 pub/sub 機制,客戶端可以從哨兵訂閱訊息。
哨兵提供的訊息訂閱頻道有很多,不同頻道包含了主從庫切換過程中的不同關鍵事件。

客戶端讀取哨兵的配置檔案後,可以獲得哨兵的地址和埠,和哨兵建立網路連線。然後,我們可以在客戶端執行訂閱命令,來獲取不同的事件訊息。

舉例:

  • 訂閱“所有例項進入客觀下線狀態的事件”:SUBSCRIBE +odown
  • 訂閱所有的事件:PSUBSCRIBE *

選舉執行

  1. 任何一個例項只要自身判斷主庫“主觀下線”後,就會給其他例項傳送 is-master-down-by-addr 命令。
  2. 接著,其他例項會根據自己和主庫的連線情況,做出 Y 或 N 的響應,Y 相當於贊成票,N 相當於反對票。
  3. 一個獲得了仲裁所需的贊成票數後,就可以標記主庫為“客觀下線”。這個所需的贊成票數是透過哨兵配置檔案中的 quorum 配置項設定的。
  4. 這個哨兵就可以再給其他哨兵傳送命令,表明希望由自己來執行主從切換,並讓所有其他哨兵進行投票。這個投票過程稱為“Leader 選舉”。成功條件:

    1. 拿到半數以上的贊成票
    2. 票數大於等於quorum

如果選舉沒有成功,那麼這輪投票就不會產生 Leader。哨兵叢集會等待一段時間(也就是哨兵故障轉移超時時間的 2 倍),再重新選舉。

注意:如果哨兵叢集只有 2 個例項,此時,一個哨兵要想成為 Leader,必須獲得 2 票,而不是 1 票。所以,如果有個哨兵掛掉了,那麼,此時的叢集是無法進行主從庫切換的。因此,通常我們至少會配置 3 個哨兵例項。

小結

哨兵叢集的關鍵機制:

  • 基於 pub/sub 機制的哨兵叢集組成過程;
  • 基於 INFO 命令的從庫列表,這可以幫助哨兵和從庫建立連線;
  • 基於哨兵自身的 pub/sub 功能,這實現了客戶端和哨兵之間的事件通知。

注意:要保證所有哨兵例項的配置是一致的,尤其是主觀下線的判斷值 down-after-milliseconds。

問題:Redis 1主4從,5個哨兵,哨兵配置quorum為2,如果3個哨兵故障,當主庫當機時,哨兵能否判斷主庫“客觀下線”?能否自動切換?
回答:
1、哨兵叢集可以判定主庫“主觀下線”。由於quorum=2,所以當一個哨兵判斷主庫“主觀下線”後,詢問另外一個哨兵後也會得到同樣的結果,2個哨兵都判定“主觀下線”,達到了quorum的值,因此,哨兵叢集可以判定主庫為“客觀下線”。
2、但哨兵不能完成主從切換。哨兵標記主庫“客觀下線後”,在選舉“哨兵領導者”時,一個哨兵必須拿到超過多數的選票(5/2+1=3票)。但目前只有2個哨兵活著,無論怎麼投票,一個哨兵最多隻能拿到2票,永遠無法達到多數選票的結果。

相關文章