Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

作者:Wen Hui
轉載:中間件小哥

Sentinel 使用和Redis服務器相同的事件處理機制:分爲文件事件和時間事件。文件事件處理機制使用I/O 多路複用來處理服務器端的網絡I/O 請求,例如客戶端連接,讀寫等操作。時間處理機制則在主循環中週期性調用時間函數來處理定時操作,例如服務器端的維護,定時更新,刪除等操作。Redis服務器主時間函數是在server.c中定義的serverCron函數,在默認情況下,serverCron會每100ms被調用一次。在這個函數中,我們看到如下代碼:

Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

其中當服務器以sentinel模式運行的時候,serverCron會調用sentinelTimer函數,來運行Sentinel中的主邏輯,sentinelTimer函數在sentinel.c中的定義如下:

Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

Sentinel Timer函數會做如下幾個操作:

  1. 檢查Sentinel當前是否在Tilt 模式(Tilt模式將會在稍後章節介紹)。
    1. 檢查Sentinel與其監控主備實例,以及其他Sentinel實例的連接,更新當前狀態,並在主實例下線的時候自動做主備倒換操作。
    2. 檢查回調腳本狀態,並做相應操作。
    3. 更新服務器頻率(調用serverCron函數的頻率),加上一個隨機因子,作用是防止監控相同主節點的Sentinel在選舉Leader的時候時間衝突,導致選舉無法產生絕對多的票數。
      其中SentinelHandleDictOfRedisInstances函數的定義如下:

Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

SentinelHandleDictOfRedisInstances函數主要做的工作是:
1.調用sentinelHandleDictOfRedisInstance函數處理Sentinel與其它特定實例連接,狀態更 新,以及主備倒換工作。

  1. 如果當前處理實例爲主實例,遞歸調用SentinelHandleDictOfRedisInstances函數處理其下屬的從實例以及其他監控這個主實例的Sentinel。
    1. 在主備倒換成功的情況下,更新主實例爲升級爲主實例的從實例。
      其中在sentinelHandleRedisInstance的定義如下:

Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

這個函數會做以下兩部分操作:

  1. 檢查Sentinel和其他實例(主備實例以及其他Sentinel)的連接,如果連接沒有設置或已經斷開連接,Sentinel會重試相對應的連接,並定時發送響應命令。 需要注意的是:Sentinel和每個主備實例都有兩個連接,命令連接和發佈訂閱連接。但是與其他監聽相同主備實例的Sentinel只保留命令連接,這部分細節會在網絡章節單獨介紹。
  2. 第二部分操作主要做的是監測主備及其他Sentinel實例,並監測其是否在主觀下線狀態,對於主實例來說,還要檢測是否在客觀下線狀態,並進行相應的主備倒換操作。
    需要注意的是第二部分操作如果Sentinel在Tilt模式下是忽略的,下面我們來看一下這個函數第二部分的的具體實現細節。
    sentinelCheckSubjectivelyDown 函數會監測特定的Redis實例(主備實例以及其他Sentinel)是否處於主觀下線狀態,這部分函數代碼如下:

Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

主觀下線狀態意味着特定的Redis實例滿足以下條件之一:

  1. 在實例配置的down_after_milliseconds時間內沒有收到Ping的回覆。
  2. Sentinel認爲實例是主實例,但收到實例爲從實例的回覆,並且上次實例角色回覆時間大於在實例配置的down_after_millisecon時間加上2倍INFO命令間隔。
    如果任何一個條件滿足,Sentinel會打開實例的S_DOWN標誌並認爲實例進入主觀下線狀態。
    主觀下線狀態意味着Sentinel主觀認爲實例下線,但此時Sentinel並沒有詢問其他監控此實例的其他Sentinel此實例的在線狀態。
    sentinelCheckObjectivelyDown 函數會檢查實例是否爲客觀下線狀態,這個操作僅僅對主實例進行。sentinelCheckObjectivelyDown函數定義如下:

Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

這個函數主要進行的操作是循環查看監控此主實例的其他Sentinel SRI_MASTER_DOWN 標誌是否打開,如果打開則意味着其他特定的Sentinel認爲主實例處於下線狀態,並統計認爲主實例處於下線狀態的票數,如果票數大於等於主實例配置的quorum值,則Sentinel會把主實例的SRI_O_DOWN標誌打開,並認爲主實例處於客觀下線狀態。
sentinelStartFailoverIfNeeded函數首先會檢查實例是否處於客觀下線狀態(SRI_O_DOWN標誌是否打開),並且在2倍主實例配置的主備倒換超時時間內沒有進行主備倒換工作,Sentinel會打開SRI_FAILOVER_IN_PROGRESS標誌並設置倒換狀態爲SENTINEL_FAILOVER_STATE_WAIT_START。並開始進行主備倒換工作。主備倒換的細節將在主備倒換的章節裏介紹。

Redis Sentinel 源碼分析 - Sentinel 的主時間事件函數

參考資料:
https://github.com/antirez/redis
https://redis.io/topics/sentinel
Redis設計與實現第二版黃健宏著

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章