1 首先clusterInit进行初始化server.cluster节点,
设置监听事件aeCreateFileEvent(server.el,cfd,AE_READABLE,clusterReadHandler,link);
2 clusterCron // 集群常规操作函数,默认每秒执行 10 次(每间隔 100 毫秒执行一次)
1 该事件用来定时向所有节点发ping消息
2 遍历所有节点,检查是否需要将某个节点标记为下线
1 node->flags |= CLUSTER_NODE_PFAIL(如果等待 PONG 回复的时长超过了限制值,将目标节点标记为 PFAIL )
2 clusterHandleSlaveFailover(如果当前节点是一个从节点,并且它正在复制的一个负责非零个槽的主节点处于 FAIL 状态,发起故障转移)nodeFailed判断节点
1 当符合转移条件需要增加纪元
server.cluster->currentEpoch++;// 增加配置纪元
server.cluster->failover_auth_epoch = server.cluster->currentEpoch;// 记录发起故障转移的配置纪元
clusterRequestFailoverAuth(向其他所有节点发送 CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 信息,看它们是否同意由这个从节点来对下线的主节点进行故障转移进行投票)
2 server.cluster->failover_auth_count >= needed_quorum(如果当前节点获得了足够多的投票,那么对下线主节点进行故障转移)
1 // 接收所有主节点负责处理的槽
for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
if (clusterNodeGetSlotBit(oldmaster,j)) {
// 将槽设置为未分配的
clusterDelSlot(j);
// 将槽的负责人设置为当前节点
clusterAddSlot(myself,j);
}
}
2 myself->configEpoch = server.cluster->failover_auth_epoch; //更新集群配置纪元
3 clusterBroadcastPong(CLUSTER_BROADCAST_ALL); //向所有节点发送 PONG 信息 通知成为主节点
3 clusterReadHandler 事件
1 clusterProcessPacket //更新当前节点为最新的currentEpoch 更新当前节点中的之前记录的send节点configEpoch
if (senderCurrentEpoch > server.cluster->currentEpoch)
server.cluster->currentEpoch = senderCurrentEpoch;
if (senderConfigEpoch > sender->configEpoch)
sender->configEpoch = senderConfigEpoch;
2 clearNodeFailureIfNeeded去掉时效的fail节点,和去掉fail_node链表分为了两部,fail_node链表是在每次判断是否要下线时根据与下线时间的超时时间确定。
2 处理发起的故障请求进行投票(接收 CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST)
clusterSendFailoverAuthIfNeeded(sender 请求当前节点为它进行故障转移投票)
1 requestCurrentEpoch < server.cluster->currentEpoch //请求的配置纪元必须大于等于当前节点的配置纪元
2 server.cluster->lastVoteEpoch == server.cluster->currentEpoch //已经投过票了直接返回,为了避免请求重复
3 遍历请求节点的槽布局
unsigned char *claimed_slots = request->myslots; 查找是否有某个槽的配置纪元大于节点请求的纪元,如果有直接退出如果有的话,因为有就说明节点请求的纪元已经过期,没有必要进行投票
if (server.cluster->slots[j] == NULL ||
server.cluster->slots[j]->configEpoch <= requestConfigEpoch)
{
continue;
}
以上三处是一致性分布式算法重要属性
4 clusterSendFailoverAuth 向节点 node 投票,支持它进行故障迁移(状态为 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK)
3 接受者根据 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK请求增加支持票数 server.cluster->failover_auth_count++;
4 这是一条 PING 、 PONG 或者 MEET 消息
1 clusterUpdateSlotsConfigWith
如果 sender 是主节点,并且 sender 的槽布局出现了变动 那么检查当前节点对 sender 的槽布局设置,看是否需要进行更新,
意思是真正的发送者负责的slot在当前节点slot的更新,并不是全量的slot更新,只是send管辖的slot的更新
if (server.cluster->slots[j] == curmaster)
newmaster = sender; // 负责槽 j 的原节点是当前节点的主节点 如果是的话,说明故障转移发生了,将当前节点的复制对象设置为新的主节点
原来负责的节点是自己,但是现在发现不是自己了,说明进行故障转移了
2 sender 处理的槽的配置纪元比当前节点已知的某个节点的配置纪元要低,如果是这样的话,通知 sender 。
3 clusterProcessGossipSection 分析并提取出消息 gossip 协议部分的信息
1 clusterNodeAddFailureReport添加 sender 对 node 的下线报告
2 markNodeAsFailingIfNeeded(node); // 尝试将 node 标记为 FAIL
clusterSendFail(node->name); //标记为 FAIL 所需的节点数量,需要超过集群节点数量的一半,当前节点是主节点的话,那么向其他节点发送报告 node 的 FAIL 信息,让其他节点也将 node 标记为 FAIL
5 type == CLUSTERMSG_TYPE_FAIL(sender 告知当前节点,某个节点已经进入 FAIL 状态)
1 failing = clusterLookupNode(hdr->data.fail.about.nodename); // 获取下线节点的消息,改变其failing->flags |= REDIS_NODE_FAIL;
1 clusterUpdateState //如果一个node节点为fail,那整个集群状态为REDIS_CLUSTER_FAIL
最后需要注意的是节点之间交换信息无所谓先后关系,但是如果节点之间要投票达成一致那就要完成一致性算法。
redis cluster分析
最新推荐文章于 2024-03-15 17:22:33 发布