6.5840 Lab3B&C

21 阅读2分钟

6.5840 Lab3A Raft Leader Election - 前情提要

log

  • Log是Leader用来对操作排序的一种手段。
  • 在一个(非Leader,也就是Follower)副本收到了操作,但是还没有执行操作时。该副本需要将这个操作存放在某处,直到收到了Leader发送的新的commit号才执行
  • Leader需要在它的Log中记录操作,因为这些操作可能需要重传给Follower。如果一些Follower由于网络原因或者其他原因短时间离线了或者丢了一些消息,Leader需要能够向Follower重传丢失的Log消息。所以,Leader也需要一个地方来存放客户端请求的拷贝。即使对那些已经commit的请求,为了能够向丢失了相应操作的副本重传,也需要存储在Leader的Log中。
  • 所有节点都需要保存Log还有一个原因,就是它可以帮助重启的服务器恢复状态。

AppendEntries

  • Leader 需要同步日志到 follower
  • Leader 需要维护 commit ,超过半数节点复制日志后commit

RequestVote

  • 不能投票给比自己日志晚的节点args.LastLogTerm < rf.logs[lastLogIndex].Term ||(args.LastLogTerm == rf.logs[lastLogIndex].Term && args.LastLogIndex < lastLogIndex)

persistence

需要持久化的参数

  • term : 用于防止节点重启后使用过期的任期,避免出现多个 Leader 或无效选举。
  • logs : 存储所有已接收但未提交/已提交的操作记录,是状态机一致性的基础。
  • vote_for : 确保同一任期内只能投一票,防止重复投票导致选举冲突。

为什么commitIndex和lastApplied不用?

  1. follower 经过正确的 AppendEntries RPC 后 日志和 Leader 相同,此时 commitIndex=min(leaderCommit, follower max index)
  2. Leader 重启后,通过比较其他节点的日志(matchIndex)重新计算 commitIndex
  3. lastApplied,状态机可以通过重放日志来实现同步。如果状态机是快照,那么在快照中会记录 lastIncludedIndexlastIncludedTerm

需要持久化的时机

当需要持久化的参数改变时,需要持久化

  • currentTerm 变更:节点发现更高任期(如收到 RPC 请求或选举超时)。
  • votedFor 变更:为某个 Candidate 投票后(响应 RequestVote)。
  • log[] 变更:追加新日志(Leader 接收客户端请求)或覆盖不一致日志(Follower 同步日志)。