Redis Sentinel源码分析(二)(四)

2014-11-24 11:29:00 · 作者: · 浏览: 3
urrent_epoch; // 设置fail over开始时间 master->failover_start_time = mstime()+rand()%s; master->failover_state_change_time = mstime(); } sentinelAskMasterStateToOtherSentinels是在检测到master状态为sdown后,sentinel向其它sentinel节点发送sentinel is-master-down-by-addr消息 void sentinelAskMasterStateToOtherSentinels(sentinelRedisInstance *master, int flags) { //遍历关注该master的sentinel节点 while((de = dictNext(di)) != NULL) { //向其它sentinle发送消息SENTINEL is-master-down-by-addr master_ip master_port current_epoch runid/* //如果本身已经开始了failover进程,则向其他sentinel节点发送自己的runid,否则发送* //注册回调函数sentinelReceiveIsMasterDownReply接受回复的信息 string(port,sizeof(port),master->addr->port); retval = redisAsyncCommand(ri->cc, sentinelReceiveIsMasterDownReply, NULL, "SENTINEL is-master-down-by-addr %s %s %llu %s", master->addr->ip, port, sentinel.current_epoch, (master->failover_state > SENTINEL_FAILOVER_STATE_NONE) server.runid : "*"); if (retval == REDIS_OK) ri->pending_commands++; } dictReleaseIterator(di); }
其他sentinel节点接受到sentinel is-master-down-by-addr消息,调用sentinelCommand处理
void sentinelCommand(redisClient *c) {
    ......
    //处理sentinel is-master-down-by-addr消息
    } else if (!strcasecmp(c->argv[1]->ptr,"is-master-down-by-addr")) {
        /* SENTINEL IS-MASTER-DOWN-BY-ADDR 
   
    
     
     
      */ ...... //根据其它sentinel传送过来的消息 ri = getSentinelRedisInstanceByAddrAndRunID(sentinel.masters, c->argv[2]->ptr,port,NULL); /* It exists  Is actually a master  Is subjectively down  It's down. * Note: if we are in tilt mode we always reply with "0". */ if (!sentinel.tilt && ri && (ri->flags & SRI_S_DOWN) && (ri->flags & SRI_MASTER)) isdown = 1; //假如发过来的信息中包含请求来源sentinel的runid,则开始进行投票 if (ri && ri->flags & SRI_MASTER && strcasecmp(c->argv[5]->ptr,"*")) { leader = sentinelVoteLeader(ri,(uint64_t)req_epoch, c->argv[5]->ptr, &leader_epoch); } //回复信息,包括isdown,leader,leader_epoch addReplyMultiBulkLen(c,3); addReply(c, isdown   shared.cone : shared.czero); addReplyBulkCString(c, leader   leader : "*"); addReplyLongLong(c, (long long)leader_epoch); if (leader) sdsfree(leader); }
     
    
   
  

sentinelReceiveIsMasterDownReply函数处理发送的给其他sentinel的消息”SENTINEL is-master-down-by-addr“的回复
void sentinelReceiveIsMasterDownReply(redisAsyncContext *c, void *reply, void *privdata) {
	......
	//根据返回值,判断是否将对应sentinel的状态置为SRI_MASTER_DOWN
	if (r->element[0]->integer == 1) {
		ri->flags |= SRI_MASTER_DOWN;
	} else {
		ri->flags &= ~SRI_MASTER_DOWN;
	}
	//如果sentinel返回了其选举的leader,则更新自己的leader和leader_epoch
	if (strcmp(r->element[1]->str,"*")) {
		sdsfree(ri->leader);
		if (ri->leader_epoch != r->element[2]->integer)
			redisLog(REDIS_WARNING,
				"%s voted for %s %llu", ri->name,
				r->element[1]->str,
				(unsigned long long) r->element[2]->integer);
		ri->leader = sdsnew(r->element[1]->str);
		ri->leader_epoch = r->element[2]->integer;
	}
}

sentinelFailoverStateMachine函数为故障转移状态机,其负责执行故障转移
void sentinelFailoverStateMachine(sentinelRedisInstance *ri) {
	//master节点&正处于failover状态则继续
	redisAssert(ri->flags & SRI_MASTER);
	if (!(ri->flags & SRI_FAILOVER_IN_PROGRESS)) return;
	switch(ri->failover_state) {
		//等待故障转移开始,如果自己为leader,置状态为SENTINEL_FAILOVER_STATE_SELECT_SLAVE,开始下一步操作,否则,不变更状态,等待fail-over完成/超时
		case SENTINEL_FAILOVER_STATE_WAIT_START:
			sentinelFailove