• Monotonic ‘Term’ acts as a logical clock to prevent time from going backwards • Operations are committed when written to a log on majority of nodes AND the term of the entry is the current term • Once committed an operation cannot be removed from the log
random timeout, one becomes candidate • Candidate increments term, requests a vote • Followers vote for the candidate if the candidate log and term are up to date
If previous log entry and term agree with the follower log contents, follower replies with success • Leader keeps track of follower log indexes, decrements index on failure and sends older data • If Majority replies with success, leader commits entry, responds to client and tells followers the latest commit index on next heartbeat
to detect failed leader or network partition and start a new election • Leader replays log to followers who are behind due to either prior failure or netsplit
states - follower, candidate, leader • Logs persistent data via rafter_log gen_server • Pure functions handling dynamic reconfiguration and quorums abstracted out to rafter_config
machines are configured differently during %% initial configuration such that one configuration includes both proposed leaders %% and the other only itself. Additionally, there is not a quorum of either %% configuration's servers running. %% %% (i.e. rafter:set_config(b, [k, b, j]), rafter:set_config(d, [i,k,b,d,o]). %% when only b and d are running.) %% candidate(#vote{term=VoteTerm, success=false}, #state{term=Term, init_config=[_Id, From]}=State) when VoteTerm > Term -> gen_fsm:reply(From, {error, invalid_initial_config}), State2 = State#state{init_config=undefined, config=#config{state=blank}}, NewState = step_down(VoteTerm, State2), {next_state, follower, NewState, NewState#state.timer_duration};