浪潮云溪数据库作为新一代分布式数据库,使用Raft共识算法实现多副本之间数据的一致性和外部读取的一致性。在云溪数据库的底层实现中,通过以下几种消息类型实现Raft机制的运行。其中,本地消息指节点创建完消息后,由自身处理该消息。节点间消息指节点在创建完消息后,将消息发送到其他节点并由这些节点处理。
Follower节点持有一个选举计时器,当节点所持有的选举计时器超过预设的选举时间阈值时,便会创建MsgHup消息。具体操作包括:
在创建出MsgHup消息后,当前Follower节点会切换成PreCandidate状态,进入下一步操作。与此同时,PreCandidate节点和Candidate节点也持有一个选举计时器,若PreCandidate节点或Candidate节点持有的选举计时器超过阈值,则会创建MsgHup消息,继续发起预选举或选举。
MsgCheckQuorum消息的作用是检测当前Leader节点是否能与Raft集群中的大部分节点通信。Leader节点持有一个心跳计时器,当心跳计时器出现超时现象时,Leader节点便会创建并发送一个MsgCheckQuorum消息。具体操作包括:
由于MsgCheckQuorum消息属于本地消息,所以当前Leader节点会收到MsgCheckQuorum消息。然后,Leader节点会根据自身记录的其他各个节点的活跃信息,判断该Leader节点与其余节点是否连通。如果不连通的节点数量超过Raft组内节点数量的一半,则节点从Leader状态切换成Follower状态。
MsgBeat消息的主要作用是探活,由Leader节点创建。在Leader节点所持有的心跳计时器出现超时现象后,便会创建MsgBeat消息。具体操作包括:
由于MsgBeat消息属于本地消息,所以当前Leader节点会收到MsgBeat消息。然后Leader节点会向其他节点发送MsgHeartbeat心跳消息。若Follower节点收到MsgHeartbeat消息,会重置自身持有的选举计时器,防止发起选举。
将节点的Leader状态转移到其他Follower节点,该过程涉及对MsgTransferLeader消息和MsgTimeoutNow消息的处理。Leader状态转移,指确定一个Follower节点作为下一个任期的Leader节点。在Leader所在的节点选择出一个合适的Follower节点后,会发送MsgTransferLeader消息交给Leader处理。Leader接收到消息后,具体操作包括:
当Follower节点接收到MsgHup本地消息时,自身会切换成PreCandidate状态,开始预选举流程。Follower节点创建MsgPreVote消息,并向其他节点广播该消息,其中MsgPreVote消息携带的Term值为节点自身记录的Term值。
集群中其他节点收到MsgPreVote消息后,对MsgPreVote消息的处理包括:
处于PreCandidate状态的节点会收到集群中其他节点返回的MsgPreVoteResp消息,当PreCandidate节点收到半数以上的同意选票时,便会切换成Candidate状态,发起正式选举。但是,若收到了拒绝选票,且MsgPreVoteResp消息中携带的Term值大于当前节点记录的Term值,则当前节点切换为Follower状态,同时自身记录的Term值置为MsgPreVoteResp消息中携带的Term值,停止接下来的选举流程。
在处于PreCandidate状态的节点收到半数以上的同意选票之后,会发起新一轮的选举,自身会切换成Candidate状态,然后向集群中的其他节点发送MsgVote消息,开始正式选举流程。
在处于Candidate状态的节点接收到MsgVoteResp消息后,对MsgVoteResp消息的处理包括:
MsgApp消息的作用是Leader节点向集群中其他节点复制Entry记录。在对MsgVote消息处理的过程中,集群中的其他节点已经切换成了Follower状态,并且它们自身记录的Term值与当前Leader节点维护的Term值相同。当Follower节点收到Leader节点发来的MsgApp消息时,会将MsgApp消息中携带的Entry记录追加到raftLog中,然后创建相应的MsgAppResp消息返回给Leader节点。
在处于Follower状态的节点接收到MsgApp消息后,对MsgApp消息的处理包括:
不论Follower节点追加Entry成功或失败,均会向Leader节点回复MsgAppResp消息。Leader节点接收到集群中其他Follower节点发送的MsgAppResp响应消息后,会根据自身记录的Follower节点的状态信息,选择不同的追加方式向其追加Entry记录,如单条追加、连续追加。若Leader节点在自身保存的Entery记录中无法找到对应Follower节点需要追加的Entry记录,便会选择发送快照的方式,向其追加Entry。
在处于Follower状态的节点接收到MsgHeartbeat消息后,对MsgHeartbeat消息的处理包括:
在处于Leader状态的节点接收到MsgHeartbeatResp消息后,对MsgHeartbeatResp消息的处理包括:
客户端通过MsgProp消息向集群发送写请求,而Raft集群中只有Leader节点能够响应客户端的写请求。当集群中的Candidate节点收到客户端发来的MsgProp消息时,会直接忽略该消息。当Follower节点收到MsgProp消息时,会将该MsgProp消息转发给Leader节点。
在处于Leader状态的节点接收到MsgProp消息后,对MsgProp消息的处理包括:
在Leader节点尝试向集群中的Follower节点发送MsgApp消息时,如果查找不到相应的Entry记录,就会通过MsgSnap消息将快照数据发送到Follower节点。Follower节点通过快照数据恢复其自身状态,从而可以与Leader节点进行正常的Entry记录追加。
在处于Follower状态的节点接收到MsgSnap消息后,对MsgSnap消息的处理包括:
该消息与Leader状态转移相关,当Follower节点接收到MsgTimeoutNow消息时,会立刻切换成Candidate状态,然后创建MsgHup消息并发起选举。
本文主要介绍了Raft共识算法在云溪数据库中定义的消息类型,通过上述介绍的消息类型,实现和保证了副本数据的同步。可以看出,云溪数据库中的Raft算法将共识分解成了几个关键模块,例如预选举模块、正式选举模块、探活模块、日志复制模块等。基于此,实现将分布式一致性的复杂问题划分为一系列的模块化问题,大大降低了算法复杂性。
|