目錄
前言
參考資料:《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 伺服器,與普通伺服器稍有區別,如下:
- 2)使用 Sentinel 專屬程式碼:使用
sentinel.c/sentinelcmds
作為伺服器的命令表,因此在 Sentinel 模式下,只能執行 PING、SENTINEL、INFO、SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE、PUNSUBSCRIBE 七個命令; - 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
頻道;
- 1)初始化伺服器:初始化一個普通的 Redis 伺服器,與普通伺服器稍有區別,如下:
2. Sentinel 與伺服器間的預設通訊
2.1 獲取主伺服器資訊
- Sentinel 預設每 10 秒向主伺服器傳送 INFO 命令;
- Sentinel 可以獲得兩方面資訊:
- 主伺服器本身資訊,如:
run_id
、role
(伺服器角色); - 主伺服器下屬所有從伺服器資訊,在以
slave
開頭的字串裡;
- 主伺服器本身資訊,如:
- Sentinel 會根據主伺服器返回的資訊做相應更新;
- 主從伺服器在
sentinelRedisInstance
結構上的區別:- flags 屬性:主伺服器為 SRI_MASTER;從伺服器為 SRI_SLAVE;
- name屬性:主伺服器為使用者配置檔案規定;從伺服器為 IP:埠號;
2.2 獲取從伺服器資訊
- 當 Sentinel 發現新的從伺服器後,會建立一個新的例項結構,同時建立連線到這個從伺服器的命令連線和訂閱連線;
- 建立命令連線後,Sentinel 預設每 10 秒向從伺服器傳送 INFO 命令;
- 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)也會為主伺服器建立自己的例項化;
3.2 建立連向其他 Sentinel 的命令連線
- 當目標 Sentinel 通過通道資訊發現一個新的源 Sentinel 時,會做兩件事:
- 為該源 Sentinel 在
sentinels
字典裡建立相應的示例結構; - 建立一個連向該源 Sentinel 的命令連線;
- 為該源 Sentinel 在
4. 檢測主觀下線狀態
- Sentinel 預設每秒向與它建立的所有例項(包括主伺服器、從伺服器和其他 Sentinel)傳送 PING 命令;
- 例項對 PING 命令的回覆有兩種情況:
- 有效回覆:例項返回 +PONG、-LOADING、-MASTERDOWN 三種之一;
- 無效回覆:返回其他;
- Sentinel 配置檔案中的
down-after-milliseconds
選項指定 Sentinel 判斷例項進入主觀下線所需的時間; - 不同 Sentinel 所設定的主觀下線時長可能不同;
- 如果某個例項在該時間內已知返回無效回覆,Sentinel 會開啟該例項
flags
的 SRI_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 的規則和方法如下:
7. 故障轉移
7.1 選出新的主伺服器
- 領頭 Sentinel 在從伺服器中選出一個狀態良好、資料完整的從伺服器。選舉規則如下:
- 選出來後,傳送 SLAVEOF no one 命令,將其設定為主伺服器;
- 領頭 Sentinel 每秒(正常是每 10 秒)向被升級的從伺服器傳送 INFO 命令,監控從伺服器的
role
屬性; - 當伺服器的
role
屬性從 slave 變成 master 時,表明順利升級;
7.2 修改從伺服器的複製目標
- 領頭 Sentinel 通過 SLAVEOF 命令讓從伺服器複製新的主伺服器;
7.3 將舊的主伺服器變成從伺服器
- 將已下線的主伺服器設定為新主伺服器的從伺服器;