redis gossip源码阅读

程序入口

int main(int argc, char **argv) {
 ...
初始化server
initServer()
...
开始事件循环
aeMain(server.el);
...
}

初始化server

int initServer(void) {
...
创建时间事件
if (aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
...
}
...
启动集群模式
if (server.cluster_enabled) clusterInit();
...
}

集群模式初始化方法

void clusterInit(void) {
...
  if (aeCreateFileEvent(server.el, server.cfd[j], AE_READABLE,
     clusterAcceptHandler, NULL) == AE_ERR)
...
}
void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
...
aeCreateFileEvent(server.el,cfd,AE_READABLE,clusterReadHandler,link);
...
}


 void clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
...
if (clusterProcessPacket(link)) {
...
}
...
}

int clusterProcessPacket(clusterLink *link) {
...
if (sender) clusterProcessGossipSection(hdr,link);
...
}
...
 if (!sender && type == CLUSTERMSG_TYPE_MEET) {
  新增节点
  clusterAddNode(node);
}
...

事件循环

void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
        if (eventLoop->beforesleep != NULL)
            eventLoop->beforesleep(eventLoop);
        处理事件
        aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
    }
}

int aeProcessEvents(aeEventLoop *eventLoop, int flags){
...
处理时间事件
    if (flags & AE_TIME_EVENTS)
        processed += processTimeEvents(eventLoop)
...
}
static int processTimeEvents(aeEventLoop *eventLoop) 
...
调用时间事件回调
retval = te->timeProc(eventLoop, id, te->clientData)
...
}


int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
...
cluster 的定时事件
    run_with_period(100) {
        if (server.cluster_enabled) clusterCron();  
...
}

gossip相关


void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {
...
添加任务节点pfail的节点数
if (clusterNodeAddFailureReport(node,sender)) {
...
判断是否需要标记节点fail
 markNodeAsFailingIfNeeded(node);
...
}


void markNodeAsFailingIfNeeded(clusterNode *node) {
...
如果自己可达,则不处理
if (!nodeTimedOut(node)) return;
如果已经在fail状态则不处理
if (nodeFailed(node)) return;
如果小于多数派,则不处理
 if (failures < needed_quorum) return;
...
如果自己是主节点则处理
if (nodeIsMaster(myself)) clusterSendFail(node->name);
...
}


 void clusterCron(void) {
发送ping
clusterSendPing(link, node->flags & CLUSTER_NODE_MEET ?CLUSTERMSG_TYPE_MEET : CLUSTERMSG_TYPE_PING);

10次后随即选取一个节点发送ping
if (!(iteration % 10)) {
...
clusterSendPing(min_pong_node->link, CLUSTERMSG_TYPE_PING);
...
}
...
判断是否超时
 delay = now - node->ping_sent;
       if (delay > server.cluster_node_timeout) {
            /* Timeout reached. Set the node as possibly failing if it is
             * not already in this state. */
            if (!(node->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL))) {
                serverLog(LL_DEBUG,"*** NODE %.40s possibly failing",
                    node->name);
              标记节点pfail
                node->flags |= CLUSTER_NODE_PFAIL;
                update_state = 1;
            }
...
}


void clusterSendPing(clusterLink *link, int type) {
...
如果节点pfail
        while((de = dictNext(di)) != NULL && pfail_wanted > 0) {
            clusterNode *node = dictGetVal(de);
            if (node->flags & CLUSTER_NODE_HANDSHAKE) continue;
            if (node->flags & CLUSTER_NODE_NOADDR) continue;
            if (!(node->flags & CLUSTER_NODE_PFAIL)) continue;
            通知其他节点此节点pfail
            clusterSetGossipEntry(hdr,gossipcount,node)
...
}


推荐阅读更多精彩内容