国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Redis 哨兵是如何完成初始化的

數據庫 Redis 安全
本文筆者將從源碼分析的角度介紹一下 Redis 哨兵是如何完成初始化的,并對 Redis 哨兵的啟動步驟做了簡單總結。

本系列終于更新到哨兵模塊的介紹,由于哨兵模塊涉及節點通信和選舉等流程,所以筆者將其分為3個篇章進行剖析,而本文筆者將從源碼分析的角度介紹一下redis哨兵是如何完成初始化的。

詳解哨兵初始化流程

1. 哨兵基本數據結構

哨兵通過raft協議實現leader選舉和故障轉移線,針對這樣一個場景,我們的哨兵一般會使用單數個,為了保證選舉的正常進行哨兵還需要記錄節一次每次進行選舉的信息維護:

  • 通過current_epoch記錄當前選舉的紀元。
  • 用masters指針所指向的字典維護當前哨兵監聽的master節點信息,每個master都會以sentinelRedisInstance結構體進行信息維護各自的name、slave等信息。
  • 通過announce_ip和announce_port用于和其他哨兵聯系時提供自身的地址信息。

對此我們給出sentinel 的結構體代碼,讀者可參考上述的介紹了解一下每一個核心字段:

struct sentinelState {
    //當前紀元
    uint64_t current_epoch;     /* Current epoch. */
    //維護主節點的哈希表指針
    dict *masters;      /* Dictionary of master sentinelRedisInstances.
    //......
    //向其他哨兵發送當前實例的地址信息
    char *announce_ip;      /* IP addr that is gossiped to other sentinels if
                               not NULL. */
    int announce_port;      /* Port that is gossiped to other sentinels if
                               non zero. */
} sentinel;

2. 初始化哨兵基本配置

redis在啟動會檢查本次啟動是否是通過redis-sentinel指令或者--sentinel參數啟動哨兵,如果是則按照哨兵模式進行初始化,默認給該節點端口號為26379并初始化哨兵sentinel:

對應的我們給出核心代碼段,可以看到main方法啟動后會檢查是否是通過redis-sentinel或者參數--sentinel啟動,如果是則將sentinel_mode 設置為1,完成后續的配置和結構體初始化:

int main(int argc, char **argv) {
   //......
   //檢查使用通過
    server.sentinel_mode = checkForSentinelMode(argc,argv);
    //......
    if (server.sentinel_mode) {
        initSentinelConfig();//初始化哨兵配置
        initSentinel();//初始化哨兵結構體
    }
 //......
}

我們步入initSentinelConfig方法可以看到配置初始化只做了一件事,即將端口號設置為26379:

void initSentinelConfig(void) {
 //將端口號設置為26379
    server.port = REDIS_SENTINEL_PORT;
}

我們再查看initSentinel這個初始化哨兵結構體的函數,可以看到其內部會將當前server執行的命令表改為哨兵的命令,以及將所有IP、端口、masters指針進行初始化:

/* Perform the Sentinel mode initialization. */
void initSentinel(void) {
    unsigned int j;

   
    //將哨兵模式的命令表改為哨兵專用命令表
    dictEmpty(server.commands,NULL);
    for (j = 0; j < sizeof(sentinelcmds)/sizeof(sentinelcmds[0]); j++) {
        int retval;
        struct redisCommand *cmd = sentinelcmds+j;

        retval = dictAdd(server.commands, sdsnew(cmd->name), cmd);
        redisAssert(retval == DICT_OK);
    }

    //紀元初始化
    sentinel.current_epoch = 0;
    //masters指針初始化
    sentinel.masters = dictCreate(&instancesDictType,NULL);
   //......
   //ip和端口號初始化
    sentinel.announce_ip = NULL;
    sentinel.announce_port = 0;
}

3. 初始化masters字典表

經歷了上一步的初始化之后,redis就會開始解析redis.conf文件中解析出所有的master信息并存入masters中,假設我們在conf文件中鍵入如下配置:

# sentinel   monitor <name> <host> <port> <quorum>
sentinel monitor masters-1 192.168.0.128  6379  1

redis就會從配置文件中匹配到sentinel 這個代碼段,然后解析出<name> <host> <port> <quorum>這幾個參數,生成一個master即可sentinelRedisInstance對象,存入masters這個字典中:

我們給出讀取redis配置的核心代碼段

void loadServerConfigFromString(char *config) {
    //......

    for (i = 0; i < totlines; i++) {
        sds *argv;
        int argc;

        linenum = i+1;
        lines[i] = sdstrim(lines[i]," \t\r\n");

        /* Skip comments and blank lines */
        if (lines[i][0] == '#' || lines[i][0] == '\0') continue;

        /* Split into arguments */
        argv = sdssplitargs(lines[i],&argc);
        if (argv == NULL) {
            err = "Unbalanced quotes in configuration line";
            goto loaderr;
        }

        /* Skip this line if the resulting command vector is empty. */
        if (argc == 0) {
            sdsfreesplitres(argv,argc);
            continue;
        }
        sdstolower(argv[0]);

        /* Execute config directives */
        if (!strcasecmp(argv[0],"timeout") && argc == 2) {
         //......
         } else if (!strcasecmp(argv[0],"sentinel")) {//如果匹配到sentinel
              //......
             //解析參數生成master信息存入哨兵的masters字典表中
                err = sentinelHandleConfiguration(argv+1,argc-1);
                if (err) goto loaderr;
            }
        }   //......
    }

     //......
}

我們再次步入sentinelHandleConfiguration可以看到大量配置參數解析的邏輯,流程比較簡單就是字符串處理,我們就以本次的監聽主節點的命令monitor為例,當redis解析到這個關鍵字則調用createSentinelRedisInstance解析出conf文件配置的master信息存入字典中:

char *sentinelHandleConfiguration(char **argv, int argc) {
    sentinelRedisInstance *ri;

    if (!strcasecmp(argv[0],"monitor") && argc == 5) {
        /* monitor <name> <host> <port> <quorum> */
        int quorum = atoi(argv[4]);

        if (quorum <= 0) return "Quorum must be 1 or greater.";
        //解析出master信息存入字典中,可以看到傳入的標識為SRI_MASTER,即當前解析并監視的對象是master節點
        if (createSentinelRedisInstance(argv[1],SRI_MASTER,argv[2],
                                        atoi(argv[3]),quorum,NULL) == NULL)
        {
            //......
        }
    } 
       //......
}

最終我們步入createSentinelRedisInstance即可看到該方法通過與運算匹配出當前傳入的信息是master的,于是拿到哨兵的masters字典表,完成master信息解析后將其存入字典中:

sentinelRedisInstance *createSentinelRedisInstance(char *name, int flags, char *hostname, int port, int quorum, sentinelRedisInstance *master) {
    //......
    //基于與運算獲得哨兵的masters表
    if (flags & SRI_MASTER) table = sentinel.masters;
    else if (flags & SRI_SLAVE) table = master->slaves;
    else if (flags & SRI_SENTINEL) table = master->sentinels;
    //......
   //創建master實例
    ri = zmalloc(sizeof(*ri));
  //......
    ri->name = sdsname;
   //......

    //存入哨兵的字典表masters中
    dictAdd(table, ri->name, ri);
    return ri;
}

4. 啟動并監聽master

完成上述步驟后,redis得知當前節點是以哨兵模式啟動,于是調用sentinelIsRunning方法,內部遍歷masters節點的信息,發送到monitor頻道告知其他當前哨兵監聽的所有monitor信息

我們從入口看起,可以看到main方法后續會判斷如果是哨兵模式則執行sentinelIsRunning:

if (!server.sentinel_mode) {
    //......
    } else {//如果是哨兵模式則如此啟動哨兵
        sentinelIsRunning();
    }

其內部調用sentinelGenerateInitialMonitorEvents遍歷masters表的信息將master發布到monitor頻道上:

void sentinelIsRunning(void) {
    //......
    //獲取masters迭代器對所有主節點設置monitor
    sentinelGenerateInitialMonitorEvents();
}

查看sentinelGenerateInitialMonitorEvents邏輯就是遍歷masters表獲取master信息調用sentinelEvent向主節點master的monitor頻道上發布消息告知當前哨兵開始監控:

void sentinelGenerateInitialMonitorEvents(void) {
    dictIterator *di;
    dictEntry *de;

    di = dictGetIterator(sentinel.masters);
    //遍歷master節點
    while((de = dictNext(di)) != NULL) {
        sentinelRedisInstance *ri = dictGetVal(de);
        //發布監聽事件
        sentinelEvent(REDIS_WARNING,"+monitor",ri,"%@ quorum %d",ri->quorum);
    }
    dictReleaseIterator(di);
}

小結

我們簡單小結一下redis哨兵的啟動步驟:

  • redis-server感知到啟動模式為哨兵模式,則按照哨兵模式進行實例初始化。
  • 加載哨兵模式支持的操作指令。
  • 解析redis.conf配置中所有master信息存儲到哨兵實例結構體的masters字典中。
  • 遍歷所有需要監控的master,向這些master的monitor頻道發布monitor事件。
  • 自此當前哨兵實例節點就開始監聽主節點。
責任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關推薦

2021-01-26 09:14:19

Linux內核模塊

2022-11-15 20:48:41

Linux

2023-11-12 23:08:17

C++初始化

2009-09-02 16:52:55

C#數組初始化

2011-03-16 10:52:20

2012-03-13 13:38:42

Java

2009-06-10 16:17:00

Netbeans JT初始化

2021-07-07 05:00:17

初始化源碼

2019-11-04 13:50:36

Java數組編程語言

2009-11-11 15:29:15

ADO初始化

2009-09-08 09:48:34

LINQ初始化數組

2011-06-17 15:29:44

C#對象初始化器集合初始化器

2021-03-12 10:30:11

SpringMVC流程初始化

2010-07-28 10:22:33

FlexApplica

2022-07-06 10:37:45

SpringServlet初始化

2020-12-03 09:50:52

容器IoC流程

2010-09-08 14:49:09

藍牙協議棧

2012-05-23 12:46:53

JavaJava類

2020-11-23 14:22:17

代碼Go存儲

2023-10-06 20:57:52

C++聚合成員
點贊
收藏

51CTO技術棧公眾號

一广人看www在线观看免费视频| 国产成人拍精品视频午夜网站| 欧美福利影院| 无套内精的网站| 久久久99久久精品女同性| 日本不卡在线视频| 国产精品一区二区婷婷| 国产精品久久久久久久久男| 久久久蜜臀国产一区二区| 国外成人福利视频| 久久视频免费在线| 国产丝袜一区二区| 久久99精品一区二区三区| 成人午夜在线影视| 欧美日韩成人一区二区三区| 欧美精品免费视频| 另类av一区二区| 美女欧美视频在线观看免费| 全球成人中文在线| 亚洲欧美日韩系列| 全国精品免费看| av男人的天堂网| 国产精品h片在线播放| 亚洲精品videosex极品| 精品99在线| 黄页免费在线观看| 成人动漫网站在线观看| 一本久道中文字幕精品亚洲嫩| 久久久久免费av| 深夜福利视频在线观看| 51精品国产人成在线观看| 日本二三区不卡| 亚洲综合欧美| 神马久久午夜| 免费拍拍拍网站| 久久精品国产2020观看福利| 亚洲国产精品成人综合 | 丝袜美腿美女被狂躁在线观看| 精品1区2区| 亚洲第一精品电影| 99麻豆久久久国产精品免费| 高清不卡一区| 美乳中文字幕| 91在线网站视频| 欧美不卡一区二区| 91视频在线观看免费| 亚洲资源网站| h网站视频在线观看| 制服丝袜综合日韩欧美| 蜜月aⅴ免费一区二区三区 | 亚洲专区中文字幕| 91精品国产黑色紧身裤美女| 国产精品18久久久久| 国产精品久久久久av蜜臀| 在线电影av| 亚洲a∨一区二区三区| 久久久噜久噜久久综合| 色欧美日韩亚洲| 99re成人在线| 亚洲mv大片欧洲mv大片| 亚洲承认视频| 瑜伽美女视频| 精品久久久久久中文字幕动漫| 中文字幕日韩精品有码视频| 亚洲影院免费观看| 久久中文欧美| 成人免费在线电影网| 色黄视频在线| 在线一区亚洲| 日韩免费观看高清| 制服丝袜中文字幕一区| 99久久er热在这里只有精品66| 日韩欧美国产精品综合嫩v| 黄色的视频在线观看| 在线黄色免费观看| 欧美日本韩国在线| 欧美国产在线视频| 日韩一区二区三区高清免费看看| 久久综合资源网| 久久一二三区| 影视先锋久久| 天天综合91| 日本www在线| sm一区二区三区| 欧美性受黑人性爽| 国产精品视频一区二区三区四| 亚洲视频第一页| 精品久久久久久国产| 国产成人自拍在线| 欧美大黑bbbbbbbbb在线| 爱情电影社保片一区| 在线资源免费观看| 日韩国产欧美亚洲| 国产日韩欧美一区二区三区四区| 欧美疯狂xxxx大交乱88av| 51午夜精品国产| 亚洲另类在线一区| 国产精选一区二区三区| 欧美精品激情| 欧美wwwwww| 成人国产二区| 2021av在线| 国产女主播在线观看| 国产人妻人伦精品| 国产精品久久久久久久电影| 亚洲天堂日韩电影| 欧美日韩在线电影| 亚洲色图清纯唯美| 波多野结衣视频一区| 国产欧美综合一区二区三区| 国产伦精品一区二区三区千人斩 | 婷婷国产在线| av免费观看网| 亚洲a∨一区二区三区| 国产精品高潮呻吟视频| 日韩精品视频在线播放| 色爱区综合激月婷婷| 亚洲欧美在线观看| 播五月开心婷婷综合| 奇米色一区二区三区四区| 自拍偷拍欧美专区| 色棕色天天综合网| 99亚洲乱人伦aⅴ精品| 日韩电影网站| а√中文在线8| 韩国福利在线| 国产91久久久久蜜臀青青天草二| www一区二区www免费| 视频一区不卡| 精品不卡一区二区三区| 亚洲一区二区三区四区视频| 欧美亚州一区二区三区| 久久国产精品久久国产精品| 亚洲欧美日韩精品久久| 精品国偷自产国产一区| 欧美视频一二三区| 欧美日韩精品在线观看| 亚洲欧美乱综合| 成人网在线播放| 日韩中文字幕区一区有砖一区| 欧美久久视频| 91高清一区| 97精品视频| 久久人体视频| 久久国产影院| 不卡一区综合视频| 欧美久久综合网| 亚洲一区av| 亚洲精品一区二区妖精| 欧美剧情片在线观看| 日韩精品一区二区三区丰满| 人人鲁人人莫人人爱精品| 国产a精品视频| 国产麻豆日韩| 国产精品国产一区| 欧美成人自拍视频| 久久九九国产视频| 亚洲尤物精选| 日韩精品在线观| 在线麻豆国产传媒1国产免费| 国产99精品视频| 高清不卡一区二区三区| xxxx日韩| 在线视频日本亚洲性| av片在线观看| 欧美日韩国产精选| 久青青在线观看视频国产| 亚洲国产欧美日韩另类综合| 亚洲精品久久久中文字幕| 国产不卡免费视频| 中文字幕欧美日韩一区二区三区| 青青草国产成人99久久| 亚洲欧洲精品一区| 国产成人自拍网| 国产美女三级视频| 91在线视频官网| 日韩中字在线观看| 国产欧美日韩综合| 国产v亚洲v天堂无码久久久 | 五月精品视频| 国产精品精品一区二区三区午夜版 | 久久综合狠狠综合久久综青草| 欧美国产高潮xxxx1819| 久久久久久国产精品免费免费| 久久中文欧美| 男人的天堂avav| 国产日韩精品视频一区| 国产午夜视频| 亚洲第一福利视频在线| 日本小视频在线免费观看| 欧美激情视频给我| 尤物网精品视频| 91淫黄看大片| 欧美三级xxx| 婷婷六月国产精品久久不卡| 日韩美女视频中文字幕| 热久久久久久久| 97在线资源| 中文字幕综合网| 调教视频免费在线观看|