前言

lab2 PartC 部分,主要涉及一个是持久化,另一个是加速的部分,写完了寒假好久,一直忘记写总结了,这里补一下。

正文

持久化

首先是持久化的部分,主要是完善下persist()函数和readPersist()部分,同步的变量论文中已经告诉我们了,主义在Make()函数调用readPersist的地方需要加锁保护。

然后我们需要思考哪些地方需要调用persist()函数

主要是:

  • 向 Leader 添加一个新的需要同步的 LogEntry 时
  • Leader 处理 AppendEntries 的回复,并且需要改变自身 term 时
  • Candidate 处理 RequestVote 的回复,并且需要改变自身 term 时
  • Receiver 处理完 AppendEntries 或者 RequestVote

加速

如何做加速呢,主要就是leader在广播时,可以根据返回包中的信息选择是否直接跳过某一段term,所以我们需要在AppendEntriesReply结构体中添加两个额外的参量来帮助leader进行判断

ConflictTerm代表PreLogIndex处冲突的term

ConflictIndex代表follower希望leader重新发送的log index即nextIndex[server]的值

然后follower需要分情况进行返回值,通常分为两种情况

ConflictTermConflictIndex
Follower 的 log 不够新,prevLogIndex 已经超出 log 长度-1(本次检查并没有发现冲突的 termlen(rf.logs) (希望从 Follower 的最后一个 index 开始下一次检查)
Follower prevLogIndex 处存在 logrf.logs[args.PrevLogIndex].TermFollower log 中属于ConflictTerm的第一个 index (期望下一次能检查之前的)

对于leader来说也要

DescriptionnextIndex
Leader 的 log 中并不存在 ConflictTerm (包括 ConflictTerm = -1 的情况)ConflictIndex
Leader 的 log 中存在 ConflictTermLeader 的 log 中存在 ConflictTerm

对于如何设置nextIndex

  1. 优化以后,理想情况是一个 RPC 能够至少检验一个 Term 的 log。
  2. Follower 在 prevLogIndex 处发现不匹配,设置好 ConflictTerm,同时 ConflictIndex 被设置为这个ConflictTerm第一个 log entry。如果 Leader 中不存在 ConflictTerm (即为-1时)则会使用 ConflictIndex 来跳过这整个 ConflictTerm 的所有 log。
  3. 如果 Follower 返回的 ConflictTerm 在 Leader 的 log 中找不到,说明这个 ConflictTerm 不会存在需要 replication 的 log。对下一个 RPC 中的 prevLogIndex 的最好的猜测就是将 nextIndex 设置为 ConflictIndex直接跳过 ConflictIndex
  4. 如果 Follower 返回的 ConflictTerm 在 Leader 的 log 中找到,说明我们还需要 replicate ConflictTerm 的某些 log,此时就不能使用 ConflictIndex 跳过,而是将 nextIndex 倒着数设置为 Leader 属于 ConflictTerm 的 log 之后的 第一个 log,这样使下一轮 prevLogIndex 能够从正确的 log 开始。

总结

大致完成了,但是有得时候还是会失败,感觉还是需要改一下。