哨兵機制
如果主庫掛了,我們就需要執行一個新主庫,比如說把一個從庫切換為主庫,把它當成主庫。
在 Redis 主從叢集中,哨兵機制是實現主從庫自動切換的關鍵機制,它有效地解決了主從複製模式下故障轉移的這三個問題。
基本任務
- 監控:主庫真的掛了嗎?
a. 採用多例項組成的叢集模式進行部署,這也被稱為哨兵叢集。
b. 引入多個哨兵例項一起來判斷, - 選主:選擇哪個從庫作為主庫?
a. 透過線上狀態、網路狀況篩選掉一部分從庫
b. 再根據優先順序、複製進度、從庫的id進行打分
c. 得分最高的就是新的主庫 - 通知:把新主庫的相關資訊通知給從庫和客戶端
監控
哨兵程式在執行時,週期性地給所有的主從庫傳送 PING 命令,檢測它們是否仍然線上執行。如果從庫沒有在規定時間內響應哨兵的 PING 命令,哨兵就會把它標記為“下線狀態”;
同樣,如果主庫也沒有在規定時間內響應哨兵的 PING 命令,哨兵就會判定主庫下線,然後開始自動切換主庫的流程。
選出新主庫
主庫掛了以後,哨兵就需要從很多個從庫裡,按照一定的規則選擇一個從庫例項,把它作為新的主庫。
通知
- 哨兵會把新主庫的連線資訊發給其他從庫,讓它們執行 replicaof 命令,和新主庫建立連線,並進行資料複製。
- 同時,哨兵會把新主庫的連線資訊通知給客戶端,讓它們把請求操作發到新主庫上。
主觀下線和客觀下線
哨兵程式會使用 PING 命令檢測它自己和主、從庫的網路連線情況,用來判斷例項的狀態。
如果哨兵發現主庫或從庫對 PING 命令的響應超時了,那麼,哨兵就會先把它標記為“主觀下線”。
- 從庫響應超時,哨兵可以直接標記為“主觀下線”
- 主庫需要哨兵叢集一起判斷,只有大多數的哨兵例項,都判斷主庫已經“主觀下線”了,主庫才會被標記為“客觀下線”
客觀下線標準:
- 當有 N 個哨兵例項時,最好要有 N/2 + 1 個例項判斷主庫為“主觀下線”,才能最終判定主庫為“客觀下線”。
- 管理員可自行設定。
重新選主
在多個從庫中,先按照一定的篩選條件,把不符合條件的從庫去掉。然後再按照一定的規則,給剩下的從庫逐個打分,將得分最高的從庫選為新主庫。
篩選條件
在選主時,除了要檢查從庫的當前線上狀態,還要判斷它之前的網路連線狀態。
判斷網路連線狀態:
down-after-milliseconds 是我們認定主從庫斷連的最大連線超時時間。
如果在 down-after-milliseconds 毫秒內,主從節點都沒有透過網路聯絡上,我們就可以認為主從節點斷連了。如果發生斷連的次數超過了 10 次,就說明這個從庫的網路狀況不好,不適合作為新主庫。
三輪打分
按照從庫優先順序、從庫複製進度以及從庫 ID 號進行打分。只要在某一輪中,有從庫得分最高,那麼它就是主庫了,選主過程到此結束。如果沒有出現得分最高的從庫,那麼就繼續進行下一輪。
- 優先順序:slave-priority 配置項
- 複製進度:slave_repl_offset 最接近 master_repl_offset
- 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 *
選舉執行
- 任何一個例項只要自身判斷主庫“主觀下線”後,就會給其他例項傳送 is-master-down-by-addr 命令。
- 接著,其他例項會根據自己和主庫的連線情況,做出 Y 或 N 的響應,Y 相當於贊成票,N 相當於反對票。
- 一個獲得了仲裁所需的贊成票數後,就可以標記主庫為“客觀下線”。這個所需的贊成票數是透過哨兵配置檔案中的 quorum 配置項設定的。
這個哨兵就可以再給其他哨兵傳送命令,表明希望由自己來執行主從切換,並讓所有其他哨兵進行投票。這個投票過程稱為“Leader 選舉”。成功條件:
- 拿到半數以上的贊成票
- 票數大於等於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票,永遠無法達到多數選票的結果。