Redis | 第12章 Sentinel 哨兵模式《Redis設計與實現》

多氯環己烷發表於2021-12-12


前言

參考資料:《Redis設計與實現 第二版》;

第四部分為多機資料庫的實現,主要由以下模組組成:複製Sentinel叢集

本篇將介紹 Redis 的Sentinel功能。Sentinel(哨兵)是 Redis 的高可用解決方案:由一個或多個 Sentinel 例項(instance)組成的 Sentinel 系統可以監視任意多個主伺服器,以及這些主伺服器屬下的所有從伺服器。在被監控的主伺服器下線時,自動將下屬的某個從伺服器升級為主伺服器,替代舊主伺服器繼續處理命令請求;

與本章相關的 Redis 命令總結在下篇文章,歡迎點選收藏,本篇將不再重複:

《Redis常用命令及示例總結(API)》https://www.cnblogs.com/dlhjw/p/15639773.html


1. 啟動並初始化 Sentinel

  • 使用以下命令:
    • $ redis-sentinel /path/to/your/sentinel.conf
    • $ redis-server /path/to/your/sentinel.conf --sentinel
  • Sentinel 啟動步驟:
    • 1)初始化伺服器:初始化一個普通的 Redis 伺服器,與普通伺服器稍有區別,如下:
      Sentinel 伺服器
    • 2)使用 Sentinel 專屬程式碼:使用 sentinel.c/sentinelcmds 作為伺服器的命令表,因此在 Sentinel 模式下,只能執行 PINGSENTINELINFOSUBSCRIBEUNSUBSCRIBEPSUBSCRIBEPUNSUBSCRIBE 七個命令;
    • 3)初始化 Sentinel 狀態:初始化一個 sentinel.c/sentinelState 結構,該結構儲存了伺服器中所有和 Sentinel 功能有關的狀態;
    • 4)初始化 Sentinel 狀態的 masters 屬性:masters 屬性是一個字典,記錄了所有被 Sentinel 監視的主伺服器的相關資訊(圖16-6);
      • 字典的鍵是被監視主伺服器的名字;
      • 字典的值是被監視主伺服器對應的 sentinel.c/sentinelRedisInstance 結構(圖16-5);
        • sentinelRedisInstance 結構裡有一個 addr 指標,指向例項的 IP 地址和埠號;
    • 5)建立連向主伺服器的網路連線:對於每個被監視的主伺服器,Sentinel 都會建立兩個連向主伺服器的非同步網路連線:
      • 命令連線:專門用於向主伺服器傳送命令,並接收命令回覆(Sentinel 是主伺服器的客戶端);
      • 訂閱連線:專門用於訂閱主伺服器的 __sentinel__:hello 頻道;

sentinelRedisInstance 結構示例
masters 字典
sentinel 與主伺服器的網路連線


2. Sentinel 與伺服器間的預設通訊

2.1 獲取主伺服器資訊

  • Sentinel 預設每 10 秒向主伺服器傳送 INFO 命令;
  • Sentinel 可以獲得兩方面資訊:
    • 主伺服器本身資訊,如:run_idrole(伺服器角色);
    • 主伺服器下屬所有從伺服器資訊,在以 slave 開頭的字串裡;
  • Sentinel 會根據主伺服器返回的資訊做相應更新;
  • 主從伺服器在 sentinelRedisInstance 結構上的區別:
    • flags 屬性:主伺服器為 SRI_MASTER;從伺服器為 SRI_SLAVE;
    • name屬性:主伺服器為使用者配置檔案規定;從伺服器為 IP:埠號;

Sentinel 分析主從伺服器結構

2.2 獲取從伺服器資訊

  • 當 Sentinel 發現新的從伺服器後,會建立一個新的例項結構,同時建立連線到這個從伺服器的命令連線和訂閱連線;
  • 建立命令連線後,Sentinel 預設每 10 秒向從伺服器傳送 INFO 命令;
  • Sentinel 會根據從伺服器返回的資訊做相應更新;
    sentinel 與從伺服器的連線

2.3 向主伺服器和從伺服器傳送資訊

  • Sentinel 預設每 2 秒通過命令連線向所有被監視的主從伺服器傳送以下格式命令:
    • PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"

    • 各引數含義如下:

      引數 含義
      s_ip Sentinel 的 IP 地址
      s_port Sentinel 的埠號
      s_runid Sentinel 的執行 ID
      s_epoch Sentinel 當前的配置紀元
      m_name 主伺服器的名字
      m_ip 主伺服器的 IP 地址
      m_port 主伺服器的埠號
      m_epoch 主伺服器當前的配置紀元

3. 接受來自主伺服器和從伺服器的頻道資訊

  • 當 Sentinel 與一個主伺服器或從伺服器建立訂閱連線後,Sentinel 會通過訂閱連線,向伺服器傳送以下命令:
    • SUBSCRIBE __sentinel__:hello
  • Sentinel 既通過命令連線向伺服器的 __sentinel__:hello 頻道傳送資訊,又通過訂閱連線從伺服器的 __sentinel__:hello 頻道接受資訊;
  • 當多個 Sentinel 監視一個伺服器時,可以通過 __sentinel__:hello 頻道的獲取資訊:
    • 如果資訊中記錄的 Sentinel 執行 ID 跟本Sentinel 一樣,說明資訊是自己發出的,丟棄這條資訊;
    • 反之,說明是其他 Sentinel 發出的;

3.1 更新 Sentinel 字典

  • 一個 Sentinel 可以通過分析接收到的頻道資訊獲知其他 Sentinel 的存在,並通過傳送頻道資訊來讓其他 Sentinel 知道自己的存在;
  • 當目標 Sentinel 接受到源 Sentinel 的訊息後,會查詢主伺服器例項結構的 sentinels 字典:
    • 如果源 Sentinel 存在,對源 Sentinel 的結構進行更新;
    • 反之,說明源 Sentinel 是剛剛監視主伺服器,將其新增到主伺服器例項結構的 sentinels 字典裡;
  • 需要注意與從伺服器的區別:sentinels 字典裡的源 Sentinel 的 flags 屬性為 SRI_SENTINEL;而從伺服器為 SRI_SLAVE
  • 下圖為 127.0.0.1:26379 的 Sentinel 為主伺服器建立的例項化,其他兩個 Sentinel (埠號為26380和26381)也會為主伺服器建立自己的例項化;

Sentinels 字典裡的 Sentinel

3.2 建立連向其他 Sentinel 的命令連線

  • 當目標 Sentinel 通過通道資訊發現一個新的源 Sentinel 時,會做兩件事:
    • 為該源 Sentinel 在 sentinels 字典裡建立相應的示例結構;
    • 建立一個連向該源 Sentinel 的命令連線;
      建立連向其他 Sentinel 的命令連線

4. 檢測主觀下線狀態

  • Sentinel 預設每秒向與它建立的所有例項(包括主伺服器、從伺服器和其他 Sentinel)傳送 PING 命令;
  • 例項對 PING 命令的回覆有兩種情況:
    • 有效回覆:例項返回 +PONG、-LOADING、-MASTERDOWN 三種之一;
    • 無效回覆:返回其他;
  • Sentinel 配置檔案中的 down-after-milliseconds 選項指定 Sentinel 判斷例項進入主觀下線所需的時間;
  • 不同 Sentinel 所設定的主觀下線時長可能不同;
  • 如果某個例項在該時間內已知返回無效回覆,Sentinel 會開啟該例項 flagsSRI_S_DOWN 標識;

5. 檢查客觀下線狀態

  • 當 Sentinel 將一個主伺服器判斷主觀下線後,會詢問其他 Sentinel。當從其他 Sentinel 接受到足夠數量的已下線判斷後,Sentinel 會將從伺服器判斷為客觀下線,並對主伺服器執行故障轉移操作;

5.1 傳送 SENTINEL is-master-down-by-addr 命令

  • 源 Sentinel 使用以下命令詢問其他 Sentinel 是否同意主伺服器已下線:

  • SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>

    引數 說明
    ip 被 Sentinel 判斷為主觀下線的主伺服器的 IP 地址
    port 被 Sentinel 判斷為主觀下線的主伺服器的埠號
    current_epoch Sentinel 當前的配置紀元,用於選舉領頭 Sentinel
    runid 可以是 * 符合(用於檢測主伺服器的客觀下線狀態)或 Sentinel 的執行 ID(用於選舉領頭 Sentinel)

5.2 接受 SENTINEL is-master-down-by-addr 命令

  • 目標 Sentinel 收到 SENTINEL 命令後,根據其中的主伺服器 IP 和埠號檢查主伺服器是否已下線;

  • 然後向源 Sentinel 返回一個包含三個引數的 Multi Bulk 作為回覆;

    引數 說明
    down_state 返回目標 Sentinel 對主伺服器的檢查結果,1代表主伺服器已下線
    leader_runid 可以是 * 符號(用於檢測主伺服器的下線狀態)或目標 Sentinel 的區域性領頭 Sentinel 的執行 ID(用於選舉領頭 Sentinel)
    leader_epoch 目標 Sentinel 的區域性領頭 Sentinel 的配置紀元,用於選舉領頭 Sentinel

5.3 接受 SENTINEL is-master-down-by-addr 命令的回覆

  • 源 Sentinel 統計其他 Sentinel 同意主伺服器已下線的數量,達到一定數量後開啟主伺服器例項結構 flags 屬性的 SRI_O_DOWN 標識,標識主伺服器已經進入客觀下線狀態;
  • 該數量可以在 Sentinel 的 quorum 引數中設定(包括源 Sentinel);
  • 不同 Sentinel 判斷客觀下線的條件可能不同;

客觀下線後的主伺服器例項


6. 選舉領頭 Sentinel

  • 當主伺服器被判斷客觀下線時,監視這個下線主伺服器的各個 Sentinel 會進行協商,選舉出一個領頭 Sentinel,並由領頭 Sentinel 對下線的主伺服器執行故障轉移操作;
  • Sentinel 系統選舉領頭 Sentinel 的方法是對 Raft 演算法的領頭選舉方法的實現;
  • Redis 選舉領頭 Sentinel 的規則和方法如下:

領頭 Sentinel 的選舉規則與方法


7. 故障轉移

7.1 選出新的主伺服器

  • 領頭 Sentinel 在從伺服器中選出一個狀態良好、資料完整的從伺服器。選舉規則如下:

主伺服器的選舉規則

  • 選出來後,傳送 SLAVEOF no one 命令,將其設定為主伺服器;

設定主伺服器

  • 領頭 Sentinel 每秒(正常是每 10 秒)向被升級的從伺服器傳送 INFO 命令,監控從伺服器的 role 屬性;
  • 當伺服器的 role 屬性從 slave 變成 master 時,表明順利升級;

主伺服器升級成功

7.2 修改從伺服器的複製目標

  • 領頭 Sentinel 通過 SLAVEOF 命令讓從伺服器複製新的主伺服器;

修改從伺服器的複製目標

7.3 將舊的主伺服器變成從伺服器

  • 將已下線的主伺服器設定為新主伺服器的從伺服器;

將舊的主伺服器變成從伺服器



最後

新人制作,如有錯誤,歡迎指出,感激不盡!
歡迎關注公眾號,會分享一些更日常的東西!
如需轉載,請標註出處!
Redis | 第12章 Sentinel 哨兵模式《Redis設計與實現》
另外,下邊有個程式設計師學習求職分享交流群
是我跟科銳國際的 HR 合作的
裡面會分享釋出一些求職就業相關的東西
也可以來交流學習技術,歡迎來玩!
掃碼新增 HR 小姐姐為好友,備註【加群】
Redis | 第12章 Sentinel 哨兵模式《Redis設計與實現》

相關文章