Sentinel(哨兵)是redis高可用的解決方案:由一個或多個Sentinel實例組成的Sentinel系統可以監視任意多個主服務器,以及這些主服務器屬下的所有從服務器,並在被監視的主服務器進行下線狀態時,自動將下線主服務器屬下的某個從服務器升級為新的主服務器。
對每個被監視的主服務器來說,Sentinel會創建兩個連向主服務器的異步網絡連接:
- 一個是命令連接,這個連接專門用來向主服務器發送命令,並接受命令回復
- 一個是訂閱連接,這個連接專門用來訂閱主服務器的——sentinel_:hello頻道
為什么需要兩個連接?
訂閱連接用來接收主服務器的消息,命令連接用來向主服務器發送命令(此時Sentinel相當於主服務器的一個客戶端)
Sentinel會默認10秒1次,通過命令連接向主服務器發送info命令,獲得主服務器以及主服務器屬下的從服務器信息。
當Sentinel發現主服務器有新的從服務器出現時,Sentinel除了會為這個新的從服務器創建相應的實例結構之外,Sentinel還會創建連接到從服務器的命令連接和訂閱連接。Sentinel也會以10秒1次向從服務器發送info命令,獲得從服務器的響應信息。
當一個Sentinel與一個主服務器或者從服務器建立起訂閱連接之后,對於監視同一個服務器的多個Sentinel來說,一個Sentinel發送的信息會被其他Sentinel接收到,這些信息會被其他Sentinel接收到,這些信息會被用於更新其他Sentinel對發送信息Sentinel的認知,也會被用於更新其他Sentinel對被監視服務器的認知。
當Sentinel通過頻道信息發現一個新的Sentinel時,會創建一個連向Sentinel的命令連接,而新的Sentinel也同樣會創建連向這個Sentinel命令連接。需要注意的是Sentinel之間不需要訂閱連接,原因在於Sentinel與主服務器,從服務器建立訂閱連接的目的就是為了獲得其他Sentinel的信息,而Sentinel之間只需要通信即可。
判斷服務器下線
Sentinel會以每秒1次的頻率向與它創建了命令連接的實例(包括主服務器,從服務器,其他Sentinel)發送PING命令,如果在指定時間長度內,該實例連續向Sentinel返回無效回復或者不回復,則Sentinel主觀認為該實例下線。
當一個Sentinel認為一個實例主觀下線后,會詢問其他Sentinel該實例是否下線,當認為下線的Sentinel數目超過閾值后,則認為該實例客觀下線。
選舉領頭Sentinel
當一個主服務器被判斷為客觀下線時,監視這個下線主服務器的各個Sentinel會進行協商,選舉一個領頭Sentinel
每個發現主服務器下線的Sentinel節點都會給其他節點發送通知,要求對方選舉自己為局部領頭,遵循先來后到的原則,一旦節點選擇了局部領頭就不會再選舉其他節點為局部領頭,如果某個節點被半數以上Sentinel節點選舉為局部領頭,則成為領頭Sentinel。如果在給定的時間內,沒有選舉出領頭Sentinel則會在一段時間后重新選舉直到選出領頭Sentinel
故障轉移
在選舉出領頭Sentinel后,領頭Sentinel對以下線的主服務器執行故障轉移操作,該操作包含三個步驟:
1.在已下線的主服務器屬下的所有到的從服務器里面,挑選出一個從服務器,並將其轉化為主服務器
2.讓已下線的主服務器屬下的所有從服務器改為復制新的主服務器
3.將以下線主服務器設置為新的主服務器的從服務器,當這個舊的主服務器重新上線時,它會成為新的主服務器的從服務器
如何選舉主服務器?
首先從主服務器的從服務器中排除不活躍的服務器(已斷線,長時間未回復領頭Sentinel的info),然后根據從服務器的優先級,選取優先級最高的服務器,如果優先級相同,則選舉復制偏移量最大的服務器,如果復制偏移量相同,則選舉id最小的服務器