聊聊Redis sentinel 機制

2023-04-17 06:00:58

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

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

 

一、為什麼需要哨兵

主從模式下,如果主庫發生故障了,那就直接會影響到從庫的同步,因為從庫沒有相應的主庫可以進行資料複製操作了。

而且,如果使用者端傳送的都是讀操作請求,那還可以由從庫繼續提供服務,這在純讀的業務場景下還能被接受。但是,一旦有寫操作請求了,按照主從庫模式下的讀寫分離要求,需要由主庫來完成寫操作。

此時,也沒有範例可以來服務使用者端的寫操作請求了,如下圖所示:

 

 無論是寫服務中斷,還是從庫無法進行資料同步,都是不能接受的。所以,如果主庫掛了,我們就需要執行一個新主庫,比如說把一個從庫切換為主庫,把它當成主庫。

 

這就涉及到三個問題:

  • 主庫真的掛了嗎?
  • 該選擇哪個從庫作為主庫?
  • 怎麼把新主庫的相關資訊通知給從庫和使用者端呢?

  

二、哨兵機制的基本流程

哨兵其實就是一個執行在特殊模式下的 Redis 程序,主從庫範例執行的同時,它也在執行。

哨兵主要負責的就是三個任務:監控、選主(選擇主庫)和通知。

 

1、監控

監控是指哨兵程序在執行時,週期性地給所有的主從庫傳送 PING 命令,檢測它們是否仍然線上執行。

如果從庫沒有在規定時間內響應哨兵的 PING 命令,哨兵就會把它標記為「下線狀態」;同樣,如果主庫也沒有在規定時間內響應哨兵的 PING 命令,哨兵就會判定主庫下線,然後開始自動切換主庫的流程。

 

2、選主

這個流程首先是執行哨兵的第二個任務,選主。

主庫掛了以後,哨兵就需要從很多個從庫裡,按照一定的規則選擇一個從庫範例,把它作為新的主庫。這一步完成後,現在的叢集裡就有了新主庫。

 

3、通知

然後,哨兵會執行最後一個任務:通知。

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

 

在這三個任務中,通知任務相對來說比較簡單,哨兵只需要把新主庫資訊發給從庫和使用者端,讓它們和新主庫建立連線就行,並不涉及決策的邏輯。但是,在監控和選主這兩個任務中,哨兵需要做出兩個決策:

  • 在監控任務中,哨兵需要判斷主庫是否處於下線狀態;
  • 在選主任務中,哨兵也要決定選擇哪個從庫範例作為主庫。

  

三、主庫下線和選主判斷

1、哨兵叢集

為了降低誤判率,在實際應用時,哨兵機制通常採用多範例的方式進行部署,多個哨兵範例通過「少數服從多數」的原則,來判斷主庫是否客觀下線。一般來說,我們可以部署三個哨兵,如果有兩個哨兵認定主庫「主觀下線」,就可以開始切換過程。當然,如果你希望進一步提升判斷準確率,也可以再適當增加哨兵個數,比如說使用五個哨兵。

 

2、如何判斷

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

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

如果檢測的是從庫,那麼,哨兵簡單地把它標記為「主觀下線」就行了,因為從庫的下線影響一般不太大,叢集的對外服務不會間斷。

但是,如果檢測的是主庫,那麼,哨兵還不能簡單地把它標記為「主觀下線」,開啟主從切換。因為很有可能存在這麼一個情況:那就是哨兵誤判了,其實主庫並沒有故障。可是,一旦啟動了主從切換,後續的選主和通知操作都會帶來額外的計算和通訊開銷。

 

3、如何選定新主庫?

一般來說,我把哨兵選擇新主庫的過程稱為「篩選 + 打分」。簡單來說,我們在多個從庫中,按照一定的篩選條件,把不符合條件的從庫去掉。