网络分区问题
网络分区导致选举永远无法达成共识,选举不断超时,任期号将不断增加
为避免这个问题,candidate会探测网络环境以免发起无意义的竞选
集群变更
leader收到配置变更要求,会广播配置变更日志,日志包括新结点和老节点,在收到老节点的多数派认可后,leader后提交该请求
在处理配置变更时同时处理写请求和竞选时,不考虑新节点的响应,只需要老节点的多数派赞同
其他问题
竞选中为什么只有一个leader?
每个follower只有一票,leader需要超过半数选票,如果没有共识,则任期被跳过
怎么保证人任期号和索引号只对应一笔预写日志?
日志值追加,不存在更新,覆盖,删除操作。同时,在同步日志时发现前一笔不相同,不同的日志会被清除
如果多数选票总是不超过半数怎么办?
一种情况,集群中只有两个节点,将永远不会达成多数公式,为此,raft保证发起竞选总是不同时的,这种情况就不会出现两个candidate,而是先发起竞选的candidate得到选票
怎么保证新的leader能拥有下线的leader的日志?
在选举时,拥有最新日志索引号的得到多数票数,因此可以保证这一点
怎么保证日志同步的幂等性
防止重复和乱序问题:同步日志时会校验上一笔日志
防止缺失问题:follower确认收到日志会发出ack响应,如果leader未收到ack响应为持续发送日志
怎么保证客户端发送的请求不丢失不重复
防止丢失问题:客户端发送请求后需要收到ack响应
防止重复问题:每一个请求都有唯一的序列号,序列号相等的请求不执行
最后一个问题
考虑这种情况
集群中有5个节点,需要3个节点可以达成共识
- T1任期,leader节点node01将日志发给node02后就下线了
- node05发现leader无响应,发起竞选并且成为新的leader(注意此时假设只有node02不给node05投票,因为node02拥有更新的日志),进入T2任期,node05当选后接收到了写请求,但是马上下线了
- node01又上线了,成为leader进入T3任期,此时node01继续未完成的同步动作,该日志变成已提交,后又下线
- node05成为新leader,进入T4任期,node05的继续将写请求同步,那么此时之前node01的数据就变成需要清除的日志了,于是违反了提交日志不能被清除的原则。
上面这种情况,node01和node05交替重复着成为leader并下线的行为
怎么规避这个问题?
第三步时T3任期,leader不应该直接提交之前T1的日志
raft规定新上任的leader需要完成现在任期的写请求后之后才能提交
在这个例子中,leader在提交之前T1的日志前需要完成T3任期的写请求
如果有了这个限制,之后node05就不会成为新的leader,应为它的日志将不会是最新的