Redis学习之Sentinel(四)
目錄
1. Sentinel簡介
Sentinel是Redis高可用性的解決方案。一個或者多個Sentinel實力可以組成一個Sentinel系統,用來監視這些主從服務器,當主服務器下線時,還可以故障轉移,重新選舉。
2. Sentinel服務器的初始化
初始化分成5個步驟
步驟一:初始化服務器
Sentinel的初始化其實跟普通的redis服務器相似,包括三個步驟:
- 初始化服務器狀態結構
- 載入配置選項
- 初始化服務器數據結構
步驟二:使用Sentinel專用代碼
普通Redis服務器使用redis.h/REDIS_SERVERPORT常量作為服務器的端口,而Sentinel使用sentinel.c/REDIS_SENTINEL_PORT常量的值作為服務器端口。
#define REDIS_SERVERPORT 6379#define REDIS_SENTINEL_PORT 26379- 普通Redis服務器使用redis.c/redisCommandTable作為服務器的命令表:
??????而Sentinel使用sentinel.c/sentinelcmds作為服務器的命令表
??????從上面的命令可以看出來,在Sentinel模式下,Reids服務器不能執行SET,DBSIZE等操作,而類似PING,SENTINEL,INFO這些命令就是客戶端可以對Sentinel執行的命令。
步驟三:初始化Sentinel狀態
Sentinel的狀態由 sentinelState結構來表示:
struct sentinelState{//當前紀元,用于實現故障轉移unit64_t current_epoch;//保存著被這個Sentinel監視的主服務器dict *masters;//是否進入TILT模式int tilt;//正在執行的腳本的數量int running_scripts;//進入TILT模式的時間mastime_t tilt_start_time;//最后一次執行時間處理器的時間mastime_t previous_time;//一個FIFO隊列,包含了所有需要執行的用戶腳本list *scripts_queue;}步驟三:初始化Sentinel狀態的masters屬性
masters字典記錄了所有被Sentinel監視的主服務器的相關信息:
- 字典的鍵是被監視的主服務器的名字
- 字典的值是被監視主服務器對應的sentinel.c/sentinelRedisInstance結構
實例的addr屬性是一個指向sentinelAddr結構的指針,保存著實例的ip地址和端口號。
typedef struct sentinelAddr{char *ip;int port; }現在初始化的Sentinel狀態的redis服務器結構為:
主從服務器的關系:
步驟五:創建連向主服務器的網絡連接
初始化Sentinel的最后一步就是創建連向被監視主服務器的網絡連接。Sentinel會創建兩個連向主服務器的異步網絡連接。
- 一個是命令連接,專門向主服務器發送命令,并接受回復。
- 一個是訂閱連接,這個連接用于訂閱主服務器的sentinel_:hello頻道。
3. Sentinel獲取主從服務器的信息
Sentinel默認會以每十秒一次的頻率,通過命令連接向被監視的服務器發送INFO命令,通過分析INFO命令的回復來獲取主服務器的當前信息。
例如發送了INFO命令,從主服務器中獲得回復如下:
#Server ··· run_id:32423ku4h23ohsdfsjklh3289fddsjk ···# Repilication role:master ··· slaver0:ip=127.0.0.1,prot=11111,state=online,offset=43,lag=0; slaver1:ip=127.0.0.1,prot=22222,state=online,offset=43,lag=0; slaver2ip=127.0.0.1,prot=33333,state=online,offset=43,lag=0; ···# Other sections因此可以獲取到主服務器本身的信息,run_id記錄了服務器運行ID,以及role域記錄了服務器角色;而且可以獲取slave的信息。因此可以根據這些域對Sentinel服務器的狀態結構進行更新。
同理,如果發送INFO命令給從服務器,從服務器會回復如下:
#Server ··· run_id:382974oilfhdsakjfhwqowrws3245df ···#Repilication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up slave_repl_offset:11887 slave_priority:100#Other sections因此,同樣可以獲取從服務器的很多信息,然后Sentinel服務器對從服務器的實例結構進行更新。
4. 向主從服務器發送接收消息
發送
默認情況下,Sentinel會以每兩秒一次的頻率向它監視的主從服務器發送以下格式的命令:
PUBLSIT __sentinel__:hello "<s_ip><s_port><s_runid><s__epoch><m_name><m_ip><m_port><m_enpoch"
其中s代表Sentinel信息, m代表主服務器信息
接收
Sentinel會通過訂閱連接,并向服務器發送以下命令:
SUBSCRIBE __sentinel__:hello
于是這個Sentinel就能訂閱這個頻道的消息。
處理消息
Sentinel為主服務器的實例結構sentinelRedisInstance有一個字段sentinels字典,儲存著監視著這個主服務器的sentinels。
所以一個Sentinel收到一條消息,它先查看消息發送者,如果是自身,那么將忽略這條消息,如果不是自身,則根據消息對sentinelRedisInstance的sentinels字典進行更新。
建立連接
當Sentinel通過頻道信息發現了一個新的Sentinel,它不僅會為新的Sentinel創建相應的數據結構,還會創建一個連向新的Sentinel的命令連接,新的Sentinel也會同樣創建一個連向這個Sentinel的連接。所以,監聽同一個服務器的幾個Sentinel會形成網絡。
5. 主觀客觀下線狀態
主觀下線 : Sentinel每秒一次向與它創建命令連接的實例發送ping命令,并通過是實例返回的ping回復來判斷是否在線。回復有+PONG,-LOADING,-MASTERDOWN和無效回復,如果不是+PONG就可以認為這個這個實例主觀下線。
客觀下線 :當Sentinel將一個主服務器判斷為主觀下線之后,為了確認這個主服務器是否真的下線了,它會向同樣監視這一個主服務器的其他Sentinel進行詢問,看他們是否也認為主服務器已經進入了下線狀態,如果數量超過sentinelRedisInstance結構中的quorum參數,那么認為客觀下線,于是就進行主服務器的選舉和故障轉移。
6. 選舉領頭Sentinel
每個Sentinel都有成為領頭的能力,而且每次選舉無論是否成功,都會將配置紀元(confuguration epoch)的值自增,它實際上就是一個計數器。
局部領頭:當一個Sentinel A向另一個Sentinel B發送請求SENTINEL is-master-down-by-addr + (Sentinel A 的 runid )代表A想成為B的局部領頭。
所以這種規則就是先到先得,最早向目標Sentinel發送這個命令的必然成為它的Sentinel,后面的命令都會無效,當它的票數超過半數時,它就成為領頭Sentinel,然后對已經下線的主服務器執行故障轉移操作。
7. 故障轉移
在選舉出領頭的Sentinel之后,領頭Sentinel對已經下線的主服務器執行故障轉移操作。步驟為:
在已下線的主服務器屬下的所有從服務器里面,挑選一個從服務器,并將其轉換為主服務器。(根據從服務器優先級,相同優先級選擇復制偏移量較大的從服務器)
讓已下線屬下的所有從服務器改為復制新的主服務器,并成為新的主服務器的從服務器。
當舊的主服務器重新上線之后,它就會成為新的主服務器的從服務器。
總結
以上是生活随笔為你收集整理的Redis学习之Sentinel(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis学习之复制(三)
- 下一篇: Redis学习之集群(五)