// A Go object implementing a single Raft peer. type Raft struct { mu sync.Mutex // Lock to protect shared access to this peer's state peers []*labrpc.ClientEnd // RPC end points of all peers persister *Persister // Object to hold this peer's persisted state me int// this peer's index into peers[] dead int32// set by Kill()
// Your data here (PartA, PartB, PartC). // Look at the paper's Figure 2 for a description of what // state a Raft server must maintain. role Role currentTerm int votedFor int
// used for election loop electionStart time.Time electionTimeout time.Duration }
注:在工程实践中,currentTerm 一般会建议用指定位数的整形,比如 int32,但这里为了简单就直接用 int 了。
// return currentTerm and whether this server // believes it is the leader. func(rf *Raft) GetState() (int, bool) { // Your code here (PartA). rf.mu.Lock() defer rf.mu.Unlock() return rf.currentTerm, rf.role == Leader }
状态转换
状态转换是针对 Peer 角色的,因此需要先定义角色类型和常量:
1 2 3 4 5 6 7
type Role string
const ( Follower Role = "Follower" Candidate Role = "Candidate" Leader Role = "Leader" )
// become a follower in `term`, term could not be decreased func(rf *Raft) becomeFollowerLocked(term int) { if term < rf.currentTerm { LOG(rf.me, rf.currentTerm, DError, "Can't become Follower, lower term") return }
LOG(rf.me, rf.currentTerm, DLog, "%s -> Follower, For T%d->T%d", rf.role, rf.currentTerm, term) // important! Could only reset the `votedFor` when term increased if term > rf.currentTerm { rf.votedFor = -1 } rf.role = Follower rf.currentTerm = term }
func(rf *Raft) becomeCandidateLocked() { if rf.role == Leader { LOG(rf.me, rf.currentTerm, DError, "Leader can't become Candidate") return }