moyuanhuang / OpenCourses

online open courses for back-end stuffs
1 stars 0 forks source link

lec 4: Raft #5

Open moyuanhuang opened 6 years ago

moyuanhuang commented 6 years ago

  1. Raft成员 基本上就是根据Figure.2 State那一栏中的定义了。我认为需要注意的成员是votedFor int,这个变量记录了当前term的leader票投给了谁,我将它初始化为-1代表本轮还未投票。一旦voteFor被赋上了非负值,说明这个peer已经投过票。在paper中有这么一句不起眼的话

Each server will vote for at most one candidate in a given term ...

因此,在term改变之前,只要voteFor非负,peer会拒绝其他所有的RequestVote RPC。除此之外,我还加上了

state string  // current state of itself: follower, candidate or leader
hasHeartbeat bool  // used for checking heartbeat
  1. constructor(Make()) 初始化一个新的raft peer。在构造器中除了对每个成员进行初始化之外,更重要的一件事就是启动一个新的goroutine来控制自己的state。对于在不同状态下的peer有不同的转换逻辑,在Figure.2的Rules for servers中给出。这里的难点在于如何在收到heartbeat后reset electionTimeOut。根据lab指导,有同学会使用time.Sleep(electionTimeOut)。我认为这样是不准确的:相当于只要Sleep的时间内收到一次heartbeat,goroutine醒来后就会重置electionTimeOut,实际上是延长了electionTimeOut时间。我的方法在这里,大概就是每隔time.Sleep(BroadcastInv)来检查heartbeat。

  2. RequestVote RPC

  3. AppendEntries RPC

moyuanhuang commented 6 years ago

迷思1:

Figure.2 rules for server: "for All servers: if RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower." Consider this scenario:

  1. L1, F1, F2正常通讯under Term 1
  2. F1网络出了问题,没收到L1的heartbeat导致timeout,自己变成Candidate。紧接着F1网络恢复,向其它peer发送RequestVote RPC,注意此时RPC中的Term已变为2。
  3. F2收到Term 为 2的RequestVote,根据规则,清空votedFor,把Term2的票投给F1。
  4. F1收到F2的票,加上自己的票,过了半数,因此变成Term2 Leader。
  5. L1收到F2的heartbeat response后检查Term发现比自己的大,退为follower。

综上,本来只是一个Follower(F2)自己的网络出了问题,最后却导致Leader改变,Term更替。这样岂不是很划不来??Term1的Leader好冤啊。而且如果Follower网络问题频繁的话,不是总得换leader?

moyuanhuang commented 6 years ago

config向Raft输入command的两种方法

sync.Cond条件变量需要在哪里使用

AppendEntries RPC