Redis | 第12章 Sentinel 哨兵模式《Redis設計與實現》
前言
參考資料:《Redis設計與實現 第二版》;
第四部分為多機資料庫的實現,主要由以下模組組成:複製、Sentinel、集群;
本篇將介紹 Redis 的Sentinel功能。Sentinel(哨兵)是 Redis 的高可用解決方案:由一個或多個 Sentinel 實例(instance)組成的 Sentinel 系統可以監視任意多個主伺服器,以及這些主伺服器屬下的所有從伺服器。在被監控的主伺服器下線時,自動將下屬的某個從伺服器升級為主伺服器,替代舊主伺服器繼續處理命令請求;
與本章相關的 Redis 命令總結在下篇文章,歡迎點擊收藏,本篇將不再重複:
《Redis常用命令及示例總結(API)》://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 將舊的主伺服器變成從伺服器
- 將已下線的主伺服器設置為新主伺服器的從伺服器;
最後

