目錄
前言
參考資料:《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 將舊的主服務器變成從服務器
- 將已下線的主服務器設置為新主服務器的從服務器;
最后

