天天看點

Redis系列4:高可用之Sentinel(哨兵模式)

Redis系列1:深刻了解高性能Redis的本質

Redis系列2:資料持久化提高可用性

Redis系列3:高可用之主從架構

1 背景

從第三篇 Redis系列3:高可用之主從架構 ,我們知道,為Redis配置主從模式,可以大幅度的提高Redis服務的可用性,減少甚至避免Redis服務發生當機的可能。

它有如下能力:

  • 故障隔離和恢複:無論主節點或者從節點當機,其他節點依然可以保證服務的正常運作,并可以手動切換主從。
  • 讀寫隔離:Master 節點提供寫服務,Slave 節點提供讀服務,分攤流量壓力,均衡流量的負載。
  • 提供高可用保障:主從模式是高可用的最基礎版本,也是哨兵模式和 cluster模式實施的前置條件。

但是依然存在不小的問題,我們知道,在衡量系統可用性這邊有個名額叫做MTTR,即平均修複時間。雖然主從模式支援手動切換,但是我們從知道服務故障到手動切換止損到恢複,這可能是一個比較長的過程。這期間的損失将難以計量,對于超高并發大系統是一個絕對災難。是以我們需要系統自動的感覺到Master故障,并選擇一個 Slave 切換為 Master,實作故障自動轉移的能力。

平均修複時間(Mean time to repair,MTTR),是描述産品由故障狀态轉為工作狀态時修理時間的平均值。

2 什麼是哨兵模式

在實際生産環境中,伺服器難免會遇到一些突發狀況:伺服器當機,停電,硬體損壞等等,一旦發生,後果不堪設想。

哨兵模式的核心還是主從模式的演變,隻不過相對于主從模式在主節點當機導緻不可寫的情況下,多了探活,以及競選機制:從所有的從節點競選出新的主節點,然後自動切換。競選機制的實作,是依賴于在系統中啟動sentinel程序,對各個伺服器進行監控。如下圖所示:

Redis系列4:高可用之Sentinel(哨兵模式)

3 哨兵模式的主要職責

我們知道,要讓Redis服務實作故障自動切換會有很多細節需要考慮,比如:

  • 判定節點故障的條件是什麼,有沒有可能是假死或者響應延遲。
  • 既然是競選機制,那麼所有slave節點都可以參與競争,也都有機會成為master。選擇哪個slave成為master是關鍵。
  • 競選出新的master,其他slave需要從新的master中replicaof,是以消息通知和通信也是核心。

帶着這些思考,我們來看看官方對Redis哨兵的定義:

哨兵作為 Redis 的一種運作模式,專注于對 Redis 執行個體(master、slaves)運作狀态進行監控,并能夠在主節點發生故障時通過一系列的操作,實作新的master競選、主從切換、故障轉移,確定整個 Redis 服務的可用性。

是以,哨兵的能力至少應該包含如下幾點:

  • 監控:持續監控 master 、slave 是否健康,是否處于預期工作狀态。
  • 主從動态切換:當 Master 運作故障,哨兵啟動自動故障恢複流程:從 slave 中選擇一台作為新 master。
  • 通知機制:競選出新的master之後,通知用戶端與新 master 建立連接配接;slave 從新的 master 中 replicaof,保障主從資料的一緻性。

接下來我們一個個來看這幾個能力的實作過程。

3.1 監控能力

哨兵模式啟用的時候,會同步啟用叫做Sentinel的程序。sentinel程會向所有的master 和 slaves 以及其他sentinel程序 發送心跳包(1s一次),看看是否正常傳回響應。

  • 如果slave 沒有在規定的時間内響應 sentinel 的 PING 指令 , sentinel 會認為該執行個體已經挂了,将它tag為:下線狀态;
  • 同理,如果master 沒有在規定時間響應 sentinel 的 PING 指令,也會被判定為 offline 狀态,隻是會多做一步 自動切換 master 的流程。

PING 指令的回複有兩種情況:

  • 有效回複:傳回 +PONG、-LOADING、-MASTERDOWN 任何一種;
  • 無效回複:有效回複之外的回複,或者指定時間内傳回任何回複。

但是可能存在一些誤判的情況,比如說網絡擁塞、master執行個體假死、請求延遲,導緻執行個體在某個短暫時間段不可用,後續又快速恢複了。

如果這時候被我們主動下線了,其實整個系統的可用性反而遭到了退化。而且 誤判之後的一系列操作,master競選、消息通知,slave 與新 master 同步資料,都會消耗大量資源。是以,誤判要不得啊。

為了保證判斷的可靠性,我們對下線的辨別做了區分:一種是 主觀下線,一種是客觀下線。

  • 主觀下線

    哨兵利用 PING 指令來監測 master、 slave 執行個體節點的生命狀态。如果是無效回複,哨兵就把這個執行個體節點标記為 主觀下線 。如果是slave,一般是有多從概念,直接下線即可,但如果是master,就要小心了。一個人sentinel容易誤判,那就多個sentinel進投票裁決。哨兵機制就是這樣的,采用多個執行個體組成sentinel叢集模式進行部署,即哨兵叢集。多個哨兵執行個體一起來判斷,就可以避免單個哨兵因為自身網絡狀況不好,而誤判主庫下線的情況。

    同時,多個哨兵的網絡同時不穩定的機率較小,由它們一起做決策,誤判率也能降低。

  • 客觀下線

    master 是否要下線不能是單個sentinel能夠決定的,上面說了我們一幫會有個sentinel叢集 ,是以這個叢集就發揮作用了,大家一起投票,超過一半的sentinel 都判斷了 主觀下線 ,這時候我們就把 master 标記為 客觀下線,認為它是真的不行了。

    當 master 被判定為 客觀下線 後,就算正式沒有master了,當務之急就是趕緊競選出一個新的master。

    Redis系列4:高可用之Sentinel(哨兵模式)
  • 如何差別主、客觀下線

    主觀下線是sentinel自己認為節點offline,這時候節點并不是真正的下線;而客觀下線是達到一定數量的哨兵(比如超過一半)都認為節點offline了,這時候會進一步觸發離線、重新競選主等一系列操作。

這裡的「一定數量」是一個法定數量(Quorum),是由哨兵監控配置決定的,解釋一下該配置:

# sentinel monitor <master-name> <master-host> <master-port> <quorum>
# 舉例如下:
sentinel monitor mymaster 127.0.0.1 6379 2
           

這條配置項用于告知哨兵需要監聽的主節點:

  • sentinel monitor:代表監控。
  • mymaster:代表主節點的名稱,可以自定義。
  • 192.168.11.128:代表監控的主節點 ip,6379 代表端口。
  • 2:法定數量,代表隻有兩個或兩個以上的哨兵認為主節點不可用的時候,才會把 master 設定為客觀下線狀态,然後進行 failover 操作。

客觀下線 的标準就是,當有 N 個哨兵執行個體時,要有 N/2 + 1 個執行個體判斷 master 為 主觀下線 ,才能最終判定 master 為 客觀下線 ,其實就是過半機制。

3.2 主從動态切換

sentinel 的一個很重要工作,就是從多個slave中選舉出一個新的master。當然,這個選舉的過程會比較嚴謹,需要通過 篩選 + 綜合評估 方式進行選舉,

3.2.1 篩選

  • 過濾掉不健康的(下線或者斷線),沒有回複哨兵ping響應的從節點。
  • 評估執行個體過往的網絡連接配接狀況

    down-after-milliseconds

    ,如果一定周期内(如24h)從庫和主庫經常斷連,而且超出了一定的門檻值(如 10 次),則該slave不予考慮。

    這樣,就保留下比較健康的執行個體了。

3.2.2 綜合評估

篩選掉不健康的執行個體之後,我們就可以對于剩下健康的執行個體按順序進行綜合評估了。

  • slave 優先級,通過 slave-priority 配置項(redis.conf),可以給不同的從庫設定不同優先級,優先級高的優先成為master。
  • 選擇資料偏移量差距最小的,即slave_repl_offset與 master_repl_offset進度差距,其實就是比較 slave 與 原master 複制進度差距。
  • slave runID,在優先級和複制進度都相同的情況下,選用runID最好的,runID越小說明建立時間越早,優先選為master。先來後到原則。

等這幾個條件都評估完,我們就會選擇出最适合slave,把他推舉為新的master。

Redis系列4:高可用之Sentinel(哨兵模式)

3.3 資訊通知

等推選出最新的master之後,後續所有的寫操作都會進入這個master中。是以需要盡快通知到所有的slave,讓他們重新 replacaof 到 master上,重建立立runID和slave_repl_offset ,來保證資料的正常傳輸和主從一緻性。如下圖所示:

Redis系列4:高可用之Sentinel(哨兵模式)

4 關于哨兵叢集

前面說過了,單個哨兵對redis執行個體的離線判斷可能會有誤判,是以會有一個sentinel叢集的概念,超過一定比例的sentinel(比如 > 1/2)的判斷為主觀下線,才能形成實質的客觀下線。

那這邊有幾個知識點我們需要梳理清楚。

4.1 叢集中的哨兵如何實作通信

使用redis的pub/sub 訂閱能力實作哨兵間通信 和 slave 發現。

哨兵之間可以互相通信,主要歸功于 Redis 的 pub/sub 釋出/訂閱機制。哨兵與 master 建立通信之後,可以利用 master 提供釋出/訂閱機制釋出自己的IP、port等資訊

master 有一個 sentinel:hello 的專用通道,用于哨兵之間釋出和訂閱消息。哨兵們都可以通過該通道釋出自己的Name、IP、Port消息,同時訂閱其他哨兵釋出的Name、IP、Port消息。互相發現之後建立起了連接配接,後續的消息通信就可以直接進行了。

★這個與微服務中的服務注冊與發現,以及RPC通信類似的整套做法類似。

Redis系列4:高可用之Sentinel(哨兵模式)

4.2 哨兵如何與slave實作連接配接

  • sentinel向master發送

    INFO

    指令
  • master傳回與之關聯的slave 清單
  • sentinel 根據 master 傳回的 slave 清單,逐個與 salve 建立連接配接,并且根據這個連接配接持續監控
    Redis系列4:高可用之Sentinel(哨兵模式)

4.3 哨兵如何與用戶端進行事件通知

依舊是通過 pub/sub 機制,釋出不同僚件,讓用戶端在這裡訂閱消息。用戶端可以訂閱哨兵的消息,哨兵提供的消息訂閱頻道有很多,不同頻道包含了主從庫切換過程中的不同關鍵事件。

5 總結

5.1 哨兵主要任務

Redis 哨兵機制是實作 Redis 不間斷服務的高可用手段之一。主從架構叢集的資料同步,是資料可靠的基礎保障;主庫當機,自動執行主從切換是服務不間斷的關鍵支撐。

Redis 哨兵機制實作了主從庫的自動切換,再也不怕跟女盆友麼麼哒的時候 master 當機了:

  • 監控 master 與 slave 運作狀态,判斷是否客觀下線;
  • master 客觀下線後,選擇一個 slave 切換成 master;
  • 通知 slave 和用戶端新 master 資訊。

5.2 哨兵叢集原理

為了避免單個哨兵故障後無法進行主從切換,以及為了減少誤判率,又引入了哨兵叢集;哨兵叢集又需要有一些機制來支撐它的正常運作:

  • 基于 pub/sub 機制實作哨兵叢集之間的通信;
  • 基于 INFO 指令擷取 slave 清單,幫助 哨兵與 slave 建立連接配接;
  • 通過哨兵的 pub/sub,實作了與用戶端和哨兵之間的事件通知。

    主從切換,并不是随意選擇一個哨兵就可以執行,而是通過投票仲裁,選擇一個 Leader,由這個 Leader 負責主從切換。

架構與思維·公衆号:撰稿者為bat、位元組的幾位高階研發/架構。不做廣告、不賣課、不要打賞,隻分享優質技術

★ 加公衆号擷取學習資料和面試集錦

碼字不易,歡迎關注,歡迎轉載

作者:翁智華

出處:https://www.cnblogs.com/wzh2010/

本文采用「CC BY 4.0」知識共享協定進行許可,轉載請注明作者及出處。

繼續閱讀