Clarification: Is the follower's term incremented when it receives a request_vote RPC?

59 views
Skip to first unread message

Jaseem Abid

unread,
Dec 15, 2015, 3:38:33 AM12/15/15
to raft...@googlegroups.com
Hey everyone, 

I'm not able to reach a final conclusion as multiple sources are giving me
slightly contradicting information.

This paragraph from the paper (copied verbatim) suggests that followers update
current term

    > To prevent this problem, servers disregard RequestVote RPCs when they
believe a current leader exists. Specifically, if a server receives a
RequestVote RPC within the minimum election timeout of hearing from a current
leader, it does not update its term or grant its vote. This does not affect
normal elections, where each server waits at least a minimum election timeout
before starting an election. However, it helps avoid disruptions from re- moved
servers: if a leader is able to get heartbeats to its cluster, then it will not
be deposed by larger term numbers.

*it does not update its term* suggests that in other occasions, the follower
does increment its term.

The 2 visualizations (thesecretlivesofdata.com as well as raftscope) update the
follower's term when a request_vote RPC is received.

I cant find a specific line in the paper where it says it should be.

The spec doesn't update follower's term.

    \* Server i receives a RequestVote request from server j with
    \* m.mterm <= currentTerm[i].
    HandleRequestVoteRequest(i, j, m) ==
        LET logOk == \/ m.mlastLogTerm > LastTerm(log[i])
                     \/ /\ m.mlastLogTerm = LastTerm(log[i])
                        /\ m.mlastLogIndex >= Len(log[i])
            grant == /\ m.mterm = currentTerm[i]
                     /\ logOk
                     /\ votedFor[i] \in {Nil, j}
        IN /\ m.mterm <= currentTerm[i]
           /\ \/ grant  /\ votedFor' = [votedFor EXCEPT ![i] = j]
              \/ ~grant /\ UNCHANGED votedFor
           /\ Reply([mtype        |-> RequestVoteResponse,
                     mterm        |-> currentTerm[i],
                     mvoteGranted |-> grant,
                     \* mlog is used just for the `elections' history variable for
                     \* the proof. It would not exist in a real implementation.
                     mlog         |-> log[i],
                     msource      |-> i,
                     mdest        |-> j],
                     m)
           /\ UNCHANGED <<state, currentTerm, candidateVars, leaderVars, logVars>>

Reply contains `mterm |-> currentTerm[i],`, Ie the follower's term, and
`currentTerm` is in the UNCHANGED set.

I checked a popular implementation (andrewjstone/rafter) and it does update the
state as well. See here

Score is 1 vs 3 now. Who wins? :)

--
Regards, 

Jaseem Abid
github.com/jaseemabid

Vipin Nair

unread,
Dec 15, 2015, 4:39:51 AM12/15/15
to raft-dev
I cant find a specific line in the paper where it says it should be.


Yeah this do not seem to be present in the paper. (Or it needs more reading up)

 
The spec doesn't update follower's term.

The spec does update the followers term. If you look at receive
block, the first thing it does on receiving any message is update
the term and then proceeds with handling the message based on its
type. Pasting the relevant section[1] below.


\* Receive a message.
Receive(m) ==
    LET i == m.mdest
        j == m.msource
    IN \* Any RPC with a newer term causes the recipient to advance
       \* its term first. Responses with stale terms are ignored.
       \/ UpdateTerm(i, j, m)
       \/ /\ m.mtype = RequestVoteRequest
          /\ HandleRequestVoteRequest(i, j, m)
       \/ /\ m.mtype = RequestVoteResponse
          /\ \/ DropStaleResponse(i, j, m)
             \/ HandleRequestVoteResponse(i, j, m)
       \/ /\ m.mtype = AppendEntriesRequest
          /\ HandleAppendEntriesRequest(i, j, m)
       \/ /\ m.mtype = AppendEntriesResponse
          /\ \/ DropStaleResponse(i, j, m)
             \/ HandleAppendEntriesResponse(i, j, m)
 

Jaseem Abid

unread,
Dec 15, 2015, 9:34:14 AM12/15/15
to raft...@googlegroups.com
On Tue, Dec 15, 2015 at 3:09 PM, Vipin Nair <swv...@gmail.com> wrote:
I cant find a specific line in the paper where it says it should be.


Yeah this do not seem to be present in the paper. (Or it needs more reading up)

To anyone who stumbles here again,  the paper states that 

>  If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower (§5.1)

(2nd bullet point under the box 'Rules for servers') 

That clarifies my question. Thanks Vipin. 

Diego Ongaro

unread,
Dec 15, 2015, 4:46:37 PM12/15/15
to raft...@googlegroups.com
 
I cant find a specific line in the paper where it says it should be.


Yeah this do not seem to be present in the paper. (Or it needs more reading up)

We get this out of the way very early in the paper when introducing the server's current term number:
Each server stores a current term number, which increases monotonically over time. Current terms are exchanged whenever servers communicate; if one server’s current term is smaller than the other’s, then it updates its current term to the larger value.

It's also in the "cheatsheet" figure, as Jaseem pointed out:
To anyone who stumbles here again,  the paper states that 

>  If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower (§5.1)

(2nd bullet point under the box 'Rules for servers') 


The spec does update the followers term. If you look at receive
block, the first thing it does on receiving any message is update
the term and then proceeds with handling the message based on its
type.
 
Thanks. In case you're interested, technically speaking, one transition in the spec is to update the follower's term as one atomic step. Later, as a different atomic step, it handles the message based on its type. That allows the behavior you might see in some implementations to first update the disk record with the new term, then later non-atomically update the disk state with a vote record. 

-Diego
Reply all
Reply to author
Forward
0 new messages