典型场景分析
场景减少,系统中共有三个节点,由于三个机器各自机器故障,无法与其他的节点完成正常的网络通信,假设三个节点的log保存的内容均是一致的。经过一段时间后,三个节点的term均不一样。
raft节点集群
- node2先恢复,开始进行leader选举,node1节点同意node2的在任期为4内的选举,随后node2成为leader,随后node3恢复选举,node1同意,node3也称为leader。集群中出现了两个leader,接下来如何解决两个leader的问题?
原来的leader node2在客户端读取、写入设置是发送心跳的时候,node1会恢复其已经过期被取代的响应,随后node2从leader变为follower - node2成为leader后,开始进行了正常的对外服务,此时node3的内容晚于node2,node3(term大于leader的term)如何加入到集群中去?
未catchup的节点不参与选举的过程,不作为大多数,避免写入的时候需要一直等待同步完成,同时如果leader发现有更大任期的节点出现时,会修改本地的任期,同时成为follower,等待下一次的选择过程 - Leader收取到Client的请求后,写入过程中未满足多数写入成功,接下来是需要进行回滚处理吗?
需要回滚
选举逻辑流程
- 只要candiade的状态才能作为备选节点,处于leader状态的节点不能参与选举过程
- 只要当前节点的term不大于vote请求中的term,同时最后的entry的term小于请求节点lastEntry的term,或者相等的时候,请求的lastindex不大于现在的lastindex,同时当前term任期内未投票给任何其它节点的情况
- term比其它节点大的时候,同时lastlog小于之外的节点的时候,会一直进行选举,但是会一直无法参与到集群当中去
成员变更
在实际的运行过程中,通常会由于某些原因进行集群本身规模的扩大,比如原来三个节点的集群需要扩充到五个节点上,当然也会有集群规模缩写的情况。下面我们来看一下整个集群怎么进行扩容的全过程。
成员变更
我们先来看一下上述的变更中会出现什么问题,由于配置变更没有办法同时达到所有节点,让所有节点在同一时刻启用新配置,因此存在某一个时刻,存在新旧两个集群的节点。
如上图所描述,集群一开始是三个节点,s1、s2、s3,假定S3是leader,从某一时刻起,新加入s4、s5两个节点,由于感知快慢不一样,s3先感知到了新的配置,由于故障问题, s3失去leader角色后又很快恢复。在这种情况下,会出现新旧两个集群,Cold集群包括s1和s3,这个集群会选取一个新的leader出来,s3、s4、s5也会选举出一个新的leader,并且双方同时可以对外提供正常的服务,整个集群本身会出现不一致性。
因此我们在整个成员变更的情况下一定不能出现这种情况,那应该怎么做呢?
我们先来看一种情况,假设集群中现在有奇数个节点,假定是2n+1个,现在我们加入一个节点,同时把这个变更知会到2n+1个节点,我们来看一下在变更的过程中是否出现两个leader节点,C old节点至少需要有n+1个节点支持,C new节点至少需要有n+2个节点,因此C old的支持者和C new支持者至少有一个是重合的,这与在一个任期内只能支持一个节点冲突。因此,加入一个节点不会出现两个leader。同样的分析过程可以作用到偶数个集群,可以得出同样的结论。












网友评论