1. 程式人生 > 其它 >Redis原始碼分析--Sentinel(1)Sentinel伺服器

Redis原始碼分析--Sentinel(1)Sentinel伺服器

一、概述:

呼叫鏈: serverCron -> sentinelTimer -> sentinelHandleDictOfRedisInstances -> sentinelHandleRedisInstance

  • 重要函式

    這裡只是給出表格,下面幾節會具體分析

    名稱 功能
    sentinelTimer 由serverCron中定時呼叫,遍歷本機(sentinel)監視的所有主伺服器;
    sentinelHandleRedisInstance 處理一個單獨例項,實現了主要邏輯;
    sentinelReconnectInstance Monitor half之一;建立連線(cc、pc);
    sentinelSendPeriodicCommands Monitor half之一;對例項進行定期操作:INFO(10s), PUBLISH (2s), PING(1s)
    sentinelCheckSubjectivelyDown 及以下都是Acting half;本機判斷一個例項是否主觀下線;
    sentinelCheckObjectivelyDown 本機判斷一個主伺服器(不是例項)是否客觀下線
    sentinelStartFailoverIfNeeded 傳送SENTINEL is-master-down,但依據狀態,會執行不同功能,之後詳解;
    sentinelFailoverStateMachine
    故障轉移狀態機;

二、伺服器如何執行Sentinel功能?:

​ 以Sentinel模式啟動的redis伺服器,會在init*Config等函式中以Sentinel模式專用程式碼替換普通redis伺服器的程式碼,這裡不細說。在serverCron定時函式中,伺服器呼叫sentinelTimer,後者會遍歷本機(sentinel)監視的所有主伺服器代表的例項(sentinelInstance)。

void sentinelTimer(void) {
    /* 判斷是否處於Tilt模式(一種保護模式,當計算機時間發生劇烈變化時發生) */
    sentinelCheckTiltCondition();
    /* 處理sentinel中的所有sentinelInstance */
    sentinelHandleDictOfRedisInstances(sentinel.masters);
	// ...
}

void sentinelHandleDictOfRedisInstances(dict *instances) {
    dictIterator *di;
    dictEntry *de;
    sentinelRedisInstance *switch_to_promoted = NULL;

    /* There are a number of things we need to perform against every master. */
    /* sentinelInstance,可以是master,slave或sentinel */
    di = dictGetIterator(instances);
    while((de = dictNext(di)) != NULL) {
        sentinelRedisInstance *ri = dictGetVal(de);
        /* 處理當前例項 */
        sentinelHandleRedisInstance(ri);
        if (ri->flags & SRI_MASTER) {
            /* 如果例項是master,遞迴處理它的slave和sentinels */
            sentinelHandleDictOfRedisInstances(ri->slaves);
            sentinelHandleDictOfRedisInstances(ri->sentinels);
            if (ri->failover_state == SENTINEL_FAILOVER_STATE_UPDATE_CONFIG) {
                switch_to_promoted = ri;
            }
        }
    }
    if (switch_to_promoted)
        sentinelFailoverSwitchToPromotedSlave(switch_to_promoted);
    dictReleaseIterator(di);
}
  • L12:sentinelHandleRedisInstance用來處理所有例項,它分為負責建立連線(cc、pc)和處理週期任務(INFO、PUBLISH、PING)的Monitor half,和負責處理邏輯的Acting half,sentinel部分的第三篇文章將介紹Monitor half,第四篇介紹Acting half。
  • L15~16:主伺服器的例項物件儲存了兩個字典,分別儲存從伺服器和所有監視它的Sentinel。所以本機遍歷處理主伺服器時,同樣會遞迴處理這些從伺服器和Sentinel。