Redis Clusterの実装-初期化(1)


まずredisからcソースコードのmain()関数が開始し、呼び出されたinitServer関数ではredisノード自体のいくつかの構成と環境を初期化する以外にcluster_を設定するかどうかによってEnabledパラメータはclusterを初期化し、以下のようにします.
 
initServer 
  //     redis.conf        cluster-enabled       yes,    cluster   
  -> if (server.cluster_enabled) clusterInit();

 
次に、clusterInit関数がredisをclusterモードに持ち込む方法を見てみましょう.
 
void clusterInit(void) {
    int saveconf = 0;
    
    /*   redisServer      clusterState       */
    server.cluster = zmalloc(sizeof(clusterState));
    server.cluster->myself = NULL;
    server.cluster->currentEpoch = 0;
    //     FAIL   
    server.cluster->state = REDIS_CLUSTER_FAIL;
    // master    
    server.cluster->size = 1;
    server.cluster->todo_before_sleep = 0;
    server.cluster->nodes = dictCreate(&clusterNodesDictType,NULL);
    server.cluster->nodes_black_list =
        dictCreate(&clusterNodesBlackListDictType,NULL);
    server.cluster->failover_auth_time = 0;
    server.cluster->failover_auth_count = 0;
    server.cluster->failover_auth_rank = 0;
    server.cluster->failover_auth_epoch = 0;
    server.cluster->lastVoteEpoch = 0;
    server.cluster->stats_bus_messages_sent = 0;
    server.cluster->stats_bus_messages_received = 0;
    memset(server.cluster->slots,0, sizeof(server.cluster->slots));
    clusterCloseAllSlots();
    /* Lock the cluster config file to make sure every node uses
     * its own nodes.conf. */
    if (clusterLockConfig(server.cluster_configfile) == REDIS_ERR)
        exit(1);
    /* Load or create a new nodes configuration. */
    
    //                  
    //       ,    createClusterNode       flags = MYSELF|MASTER     
    if (clusterLoadConfig(server.cluster_configfile) == REDIS_ERR) {
        /* No configuration found. We will just use the random name provided
         * by the createClusterNode() function. */
        myself = server.cluster->myself =
            createClusterNode(NULL,REDIS_NODE_MYSELF|REDIS_NODE_MASTER);
        redisLog(REDIS_NOTICE,"No cluster configuration found, I'm %.40s",
            myself->name);
            
        //        cluster   nodes hash table  
        //   nodes        nodeName -> node   hash  
        clusterAddNode(myself);
        saveconf = 1;
    }
    
    //             cluster-config-file    
    if (saveconf) clusterSaveConfigOrDie(1);
    /* We need a listening TCP port for our cluster messaging needs. */
    server.cfd_count = 0;
    /* Port sanity check II
     * The other handshake port check is triggered too late to stop
     * us from trying to use a too-high cluster port number. */
    //         ,   redis                55535,        
    // cluster         > 65535    
    if (server.port > (65535-REDIS_CLUSTER_PORT_INCR)) {
        redisLog(REDIS_WARNING, "Redis port number too high. "
                   "Cluster communication port is 10,000 port "
                   "numbers higher than your Redis port. "
                   "Your Redis port number must be "
                   "lower than 55535.");
        exit(1);
    }
    
    //    cluster            
    if (listenToPort(server.port+REDIS_CLUSTER_PORT_INCR,
        server.cfd,&server.cfd_count) == REDIS_ERR)
    {
        exit(1);
    } else {
        int j;
        
        //                   ACCEPT      
        //                   ( :Linux    epoll,     aeApiAddEvent   )
        //       clusterAcceptHandler      ACCEPT      
        for (j = 0; j  keys map is a sorted set. Init it. */
    server.cluster->slots_to_keys = zslCreate();
    /* Set myself->port to my listening port, we'll just need to discover
     * the IP address via MEET messages. */
    myself->port = server.port;
    resetManualFailover();
}

 
この部分のソースコードから、Redis Cluster初期化部分の核心は主にnodesであることがわかる.confのロードとcluster busチャネルのリスニングサービスの起動の2つの部分:
1,nodes.confのロードまたは作成:まずノード構成をロードする(clusterLoadConfig()関数実装を表示し、ここでは展開しない)ことがソースコードからわかりますが、存在しない場合やファイルコンテンツ長が0の場合は、ノード構成が新しく作成され、初期作成はこのノードの構成情報のみが含まれます.nodes.conf構成の例は次のとおりです.
$ cat nodes.conf 
8868592d98d84b7cf5752cc0b97af4ac807d1a12 127.0.0.1:7007 slave bfc910f924d772fe03d9fe6a19aabd73d5730d26 0 1410882108055 8 connected
f5bdda1518cd3826100a30f5953ed82a5861ed48 127.0.0.1:7002 slave bfc910f924d772fe03d9fe6a19aabd73d5730d26 0 1410882107151 8 connected
82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4 127.0.0.1:7001 master - 0 1410882106146 2 connected 6461-10922
61dfb1055760d5dcf6519e35435d60dc5b207940 127.0.0.1:7004 slave 82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4 0 1410882107651 5 connected
6d1ebedad33bb31ffbaa99bad095eef4a5920857 127.0.0.1:7006 master - 0 1410882106648 0 connected
bfc910f924d772fe03d9fe6a19aabd73d5730d26 127.0.0.1:7005 master - 0 1410882106648 8 connected 11923-16383
35e0f6fdadbf81a00a1d6d1843698613e653867b 127.0.0.1:7003 slave 123ed65d59ff22370f2f09546f410d31207789f6 0 1410882106146 7 connected
123ed65d59ff22370f2f09546f410d31207789f6 127.0.0.1:7000 myself,master - 0 0 7 connected 0-6460 10923-11922
vars currentEpoch 8 lastVoteEpoch 8

 
ここには、0 NodeID:6 d 1 ebedad 33 bb 31 ffbaa 99 bad 095 eef 4 a 5920857 1ノードのIP:Port:127.0.0.1:7006 2 flag:ノードを識別するいくつかのオプション、オプション値はmaster|slave|myself|fail|fail?|fail?|handshake|noaddr|noflags、clusterNodeに対応する.flags 3 masterノードID:slaveノードの場合、masterノードのIDが表示されます.そうでない場合、表示-このノードがmasterノード4がpingを最後に送信した時間5がpongを最後に受信した時間6 configEpoch 7接続状態8がmasterノードに対して、最後のフィールドには、処理されたslots範囲が記録されます.migrationの場合、フォーマットは[slots->nodeIdで、slotsで指定したスロットビットをnodeIdに移行することを示します.2)varsの先頭の行で、現在は主に2つの変数currentEpochとlastVoteEpochの値が記録されています(以下、epochを個別に分析します).