如果有哨兵實例在運行時發生了故障,主從庫還能正常切換嗎?
直接拋結論,可能可以。實際上,一旦多個實例組成了哨兵集群,即使有哨兵實例出現故障掛掉了,其他哨兵還能繼續協作完成主從庫切換的工作,包括判定主庫是不是處于下線狀態,選擇新主庫,以及通知從庫和客戶端。那為什么是可能呢?這就要了解哨兵工作的基本原理了。
基于 pub/sub 機制的哨兵集群組成
在配置哨兵的信息時,我們只需要設置主庫的 IP 和端口,并沒有配置其他哨兵的連接信息,因為哨兵不需要知道其他的哨兵信息。那么哨兵之間是如何互相發現的呢?這要歸功于 Redis 提供的 pub/sub 機制,也就是發布 / 訂閱機制。實際上,哨兵只要和主庫建立起了連接,就可以在主庫上發布消息了,比如說發布它自己的連接信息(IP 和端口)。同時,它也可以從主庫上訂閱消息,獲得其他哨兵發布的連接信息。當多個哨兵實例都在主庫上做了發布和訂閱操作后,它們之間就能知道彼此的 IP 地址和端口。
除了哨兵實例,我們自己編寫的應用程序也可以通過 Redis 進行消息的發布和訂閱。所以,為了區分不同應用的消息,Redis 會以頻道的形式,對這些消息進行分門別類的管理。所謂的頻道,實際上就是消息的類別。當消息類別相同時,它們就屬于同一個頻道。反之,就屬于不同的頻道。只有訂閱了同一個頻道的應用,才能通過發布的消息進行信息交換。
哨兵除了彼此之間建立起連接形成集群外,還需要和從庫建立連接。這是因為,在哨兵的監控任務中,它需要對主從庫都進行心跳判斷,而且在主從庫切換完成后,它還需要通知從庫,讓它們和新主庫進行同步。
哨兵是如何知道從庫的 IP 地址和端口的呢?
這是由哨兵向主庫發送 INFO 命令來完成的。哨兵給主庫發送 INFO 命令,主庫接受到這個命令后,就會把從庫列表返回給哨兵。接著,哨兵就可以根據從庫列表中的連接信息,和每個從庫建立連接,并在這個連接上持續地對從庫進行監控。通過 pub/sub 機制,哨兵之間可以組成集群,同時,哨兵又通過 INFO 命令,獲得了從庫連接信息,也能和從庫建立連接,并進行監控了。
為什么客戶端也需要知道新主庫的連接信息?
- 客戶端只有知道新主庫的連接信息,才能向新主庫發送請求操作。
- 有時會遇到這樣的問題:如何在客戶端通過監控了解哨兵進行主從切換的過程呢?比如說,主從切換進行到哪一步了?這其實就是要求,客戶端能夠獲取到哨兵集群在監控、選主、切換這個過程中發生的各種事件。
基于 pub/sub 機制的客戶端事件通知
從本質上說,哨兵就是一個運行在特定模式下的 Redis 實例,只不過它并不服務請求操作,只是完成監控、選主和通知的任務。所以,每個哨兵實例也提供 pub/sub 機制,客戶端可以從哨兵訂閱消息。哨兵提供的消息訂閱頻道有很多,不同頻道包含了主從庫切換過程中的不同關鍵事件。具體的操作步驟是,客戶端讀取哨兵的配置文件后,可以獲得哨兵的地址和端口,和哨兵建立網絡連接。然后,我們可以在客戶端執行訂閱命令,來獲取不同的事件消息。
由哪個哨兵執行主從切換?
確定由哪個哨兵執行主從切換的過程,和主庫“客觀下線”的判斷過程類似,也是一個“投票仲裁”的過程。
實例進行“客觀下線”的仲裁過程
- 任何一個實例只要自身判斷主庫“主觀下線”后,就會給其他實例發送 is-master-down-by-addr 命令。接著,其他實例會根據自己和主庫的連接情況,做出 Y 或 N 的響應,Y 相當于贊成票,N 相當于反對票。
- 一個哨兵獲得了仲裁所需的贊成票數后,就可以標記主庫為“客觀下線”。這個所需的贊成票數是通過哨兵配置文件中的 quorum 配置項設定的。例如,現在有 5 個哨兵,quorum 配置的是 3,那么,一個哨兵需要 3 張贊成票,就可以標記主庫為“客觀下線”了。這 3 張贊成票包括哨兵自己的一張贊成票和另外兩個哨兵的贊成票。
- 此時,這個哨兵就可以再給其他哨兵發送命令,表明希望由自己來執行主從切換,并讓所有其他哨兵進行投票。這個投票過程稱為“Leader 選舉”。因為最終執行主從切換的哨兵稱為 Leader,投票過程就是確定 Leader。
- 在投票過程中,任何一個想成為 Leader 的哨兵,要滿足兩個條件:第一,拿到半數以上的贊成票;第二,拿到的票數同時還需要大于等于哨兵配置文件中的 quorum 值。以 3 個哨兵為例,假設此時的 quorum 設置為 2,那么,任何一個想成為 Leader 的哨兵只要拿到 2 張贊成票,就可以了。
- 如果本輪沒有選出來 Leader,那么這輪投票就不會產生 Leader。哨兵集群會等待一段時間(也就是哨兵故障轉移超時時間的 2 倍),再重新選舉。這是因為,哨兵集群能夠進行成功投票,很大程度上依賴于選舉命令的正常網絡傳播。如果網絡壓力較大或有短時堵塞,就可能導致沒有一個哨兵能拿到半數以上的贊成票。所以,等到網絡擁塞好轉之后,再進行投票選舉,成功的概率就會增加。
- 需要注意的是,如果哨兵集群只有 2 個實例,此時,一個哨兵要想成為 Leader,必須獲得 2 票,而不是 1 票。所以,如果有個哨兵掛掉了,那么,此時的集群是無法進行主從庫切換的。因此,通常我們至少會配置 3 個哨兵實例。這一點很重要,你在實際應用時可不能忽略了。