Redis 哨兵架構
1. 主從複製架構的侷限
可用性有限:當Master
宕機後,此時寫操作都失敗,直到實例重啓。
爲解決Master
到實例重啓所丟失的數據量,提出了哨兵架構。
2. 哨兵架構
哨兵架構示意圖如下:
優點
可以監視任意多個主服務器,以及這些主服務器屬下的所有從服務器,並在被監視的主服務器進人下線狀態時,自動將下線主服務器屬下的某個從服務器升級爲新的主服務器,然後由新的主服務器代替已下線的主服務器繼續處理命令請求。
這樣就不需要等待運維人員重啓實例,而是自動的進行選舉,只不過是在選舉的時刻不能進行寫操作,可用性極大的提高了。
3. 哨兵工作步驟
當主服務的server1
的下線時長超過用戶設定的下線時長上限時,Sentinel
系統就會對server1
執行故障轉移操作:
- 首先,
Sentinel
系統會挑選server1
屬下的其中一個從服務器,並將這個被選中的從服務器升級爲新的主服務器。 - 之後,
Sentinel
系統會向server
1屬下的所有從服務器發送新的複製指令,讓它們成爲新的主服務器的從服務器,當所有從服務器都開始複製新的主服務器時,故障轉移操作執行完畢。 - 另外,
Sentinel
還會繼續監視已下線的server1
,並在它重新上線時,將它設置爲新的主服務器的從服務器。
4. 獲取主服務器信息
Sentinel 默認以每10秒一次的頻率,向被監視的主服務器發送INFO
命令,通過其回覆來獲取主服務器的當前信息。
通過分析主服務器返回的INFO
命令回覆,Sentinel
可以獲取以下兩方面的信息:
- 主服務器自身信息,服務器的運行
ID
以及服務器的角色 - 主服務器的所有從服務器,如從服務器的
IP
、端口,所以Sentinel
無須用戶提供從服務器地址信息就可以自動發現從服務器。
5. 獲取從服務器信息
當 Sentinel
發現主服務器有新的從服務器時,Sentinel
除了爲該從服務器創建相應的實例,還會創建連接向從服務器的命令連接和頻道連接。
當創建命令連接後,Sentinel 默認會以每10秒一次的頻率通過命令連接向從服務器發送 INFO 命令。
根據INFO
命令的回覆,Sentinel
會提取出以下信息:
- 從服務器的運行ID
- 從服務器的角色
- 主服務器的ip、端口
- 從服務器的優先級
- 從服務器的複製偏移量
6. 向主服務器和從服務器發送信息
在默認情況下,Sentinel
會以每兩秒一次的頻率。 通過命令連接向所有被監視的主服務器和從服務器發送以下格式的命令:
PUBLISH __sentinel:he11o "<s_ ip>,<s_ port>,<s_ runid>,<s_ epoch>,<m_ name>,<m_ip>, <m_port>, <m_ epoch> "
s_
開頭的參數爲Sentinel
本身的信息。
m_
開頭的參數爲Master
本身的信息。
7. 接受來自主服務器和從服務器的頻道信息
當Sentinel
與一個主服務器或者從服務器建立起訂閱連接之後,Sentinel
就會通過訂閱連接,向服務器發送以下命令:
SUBSCRIBE __sentinel___ : hel1o
Sentinel
對sentinel__ :hello
頻道的訂閱會一直持續到Sentinel
與服務器的連接斷開爲止。
Sentinel
會從頻道中獲取到的信息,對對應主服務器的實例結構進行更新。
7. 檢測主觀下線
默認情況下,Sentinel
會以每秒一次的頻率向所有與他創建了命令連接的實例(包括主服務器、從服務器、其他Sentinel
)發送 PING
命令,並通過實例返回的信息判斷實例是否在線。
如果有一個實例在 down-after-millisecond
毫秒內,連續向 Sentinel
返回無效回覆,那麼 Sentinel
會修改這個實例所對應的實例結構,在結構的flags
屬性中打開 SRI_S_DOWN
標識,以此標識該實例已經進入主觀下線狀態。
8. 檢測客觀下線
當 Sentinel
將一個主服務器判斷爲主觀下線後,爲了確保該主服務器真的下線,還需要進行客觀下線判斷。
當 Sentinel
從其他 Sentinel
那裏接收到足夠數量的下線判斷後,Sentinel
就會將主服務器判定爲客觀下線,並對服務器進行故障轉移操作。
9. 選舉領頭 Sentinel
當一個主服務器被判斷爲客觀下線時,監視這個下線主服務器的各個Sentinel
會進行協商,選舉出一個領頭Sentinel, 並由領頭
Sentinel `對下線主服務器執行故障轉移操作。
領頭Sentinel
選舉的規則和方法:
10. 故障轉移
領頭 Sentinel
將進行故障轉移時,需執行以下3
個步驟:
- 在已下線主服務器屬下的所有從服務器裏面,挑選出一個從服務器,並將其轉換爲主服務器。
- 讓已下線主服務器屬下的所有從服務器改爲複製新的主服務器。
- 將已下線主服務器設置爲新的主服務器的從服務器,當這個舊的主服務器重新上線時,它就會成爲新的主服務器的從服務器。
10.1 選出新的主服務器
選舉規則
領頭服務器將所有從服務器保存到一個列表中,然後進行過濾。
- 刪除所有處於下線或掉線的從服務器
- 刪除最近 5 秒內沒有回覆過領頭
Sentinel
的INFO
命令的從服務器 - 刪除所有與主服務器連接斷開超過
down-after-miliseconds * 10
的從服務器 - 根據從服務器的優先級進行排序,選擇優先級最高的
- 如果優先級相同,選擇
offset
最大的,保證數據儘可能一致 - 如果
offset
相同,則出run ID
最小的從服務器
10.2 修改從服務器的複製目標
當新的主服務器出現之後,領頭 Sentinel
下一步要做的就是,讓已下線主服務器屬下的所有從服務器去複製新的主服務器,這一動作可以通過向從服務器發送 SLAVEOF
命令來實現。
10.3 將舊的主服務器變爲從服務器
故障轉移操作最後要做的是,將已下線的主服務器設置爲新的主服務器的從服務器。
11. 集羣腦裂
腦裂,也就是說,某個master
所在機器突然脫離了正常的網絡,跟其他slave
機器不能連接,但是實際上master
還運行着。
此時哨兵可能就會認爲master
宕機了,然後開啓選舉,將其他slave
切換成了master
。
這個時候,集羣裏就會有兩個·master
,也就是所謂的腦裂。
這會造成客戶端還沒有反應過來,數據沒有被寫入到新的master
中,從而造成數據不一致。
解決方案
min-slaves-to-write 1
min-slaves-max-lag 10
第一個參數表示連接到master
的最少slave數量爲 1
第二個參數表示slave
連接到master
的最大延遲時間爲 10 秒
如果說一旦所有的slave
,數據複製和同步的延遲都超過了10
秒鐘,那麼這個時候,master
就不會再接收任何請求了。
該方案同樣是解決異步同步數據丟失的解決方案。