面试题答案
一键面试Raft算法实现分布式存储系统数据一致性
- 选举过程
- 角色:Raft 中有三种角色,分别是领导者(Leader)、跟随者(Follower)和候选人(Candidate)。初始状态下,所有节点都是跟随者。
- 选举触发:跟随者在一段时间内(选举超时时间,每个节点的选举超时时间在一个范围内随机取值)没有收到领导者的心跳(AppendEntries 消息),就会转换为候选人,并发起选举。
- 投票流程:候选人向其他节点发送 RequestVote 消息,请求它们给自己投票。每个节点在一个选举周期内只能投一票,按照先来先得的原则。如果候选人收到超过半数节点的投票,就会当选为领导者。
- 心跳机制:领导者当选后,定期向跟随者发送心跳消息(AppendEntries 消息,包含空日志条目),以维持其领导地位并通知跟随者它仍然存活。跟随者收到心跳后,会重置其选举超时时间。
- 日志复制机制
- 日志结构:每个节点都有一个日志,日志由一系列的日志条目组成。每个日志条目包含指令(如存储数据的操作)和该条目的任期号(Term)。任期号用于标识选举周期,每次选举都会产生一个新的任期号。
- 日志复制流程:客户端向领导者发送写请求,领导者将该请求封装成一个日志条目,添加到自己的日志中,并将该日志条目通过 AppendEntries 消息发送给所有跟随者。跟随者收到 AppendEntries 消息后,会检查消息中的任期号和前一个日志条目的索引和任期号是否匹配。如果匹配,就将日志条目添加到自己的日志中,并向领导者发送一个包含成功或失败状态的响应。
- 日志匹配原则:领导者和跟随者的日志必须保持匹配。如果领导者发现跟随者的日志与自己不一致,会通过 AppendEntries 消息将跟随者的日志截断到与自己一致的位置,然后重新发送后续的日志条目。
- 提交日志:当领导者收到超过半数跟随者对某个日志条目的确认时,就认为该日志条目已提交。领导者会将已提交的日志应用到状态机(执行实际的数据存储操作),并通知跟随者该日志条目已提交,跟随者也会将该日志条目应用到自己的状态机。
- 处理节点故障和网络分区
- 节点故障:
- 领导者故障:如果领导者发生故障,跟随者在选举超时后会发起新一轮选举。由于领导者故障,其他节点不会再收到心跳,从而触发选举。新的选举会选出一个新的领导者,新领导者会从自己的日志中继续复制尚未提交的日志条目给跟随者。
- 跟随者故障:如果跟随者发生故障,领导者会在一定时间内不断尝试向其发送 AppendEntries 消息。当跟随者恢复后,领导者会根据日志匹配原则,将跟随者的日志更新到与自己一致的状态。
- 网络分区:
- 分区情况分析:网络分区会导致集群被分成多个子集群。在这种情况下,每个子集群内的节点可能会进行选举。
- 分区处理方式:由于只有超过半数节点的子集群才能选出领导者,所以只有包含原领导者且节点数超过半数的子集群能正常工作(如果原领导者在该子集群中,它依然是领导者;如果不在,会选出新领导者)。其他节点数不超过半数的子集群无法选出领导者,只能等待网络恢复。当网络恢复后,各个子集群重新连通,领导者会将自己的日志同步给其他子集群中的节点,使整个集群的数据重新达到一致。
- 节点故障: