Reading — step 1 of 5
Figure-8: Commit From a Prior Term
Figure-8: Commit From a Prior Term
The most subtle safety bug in Raft. From the paper's Figure 8 (Ongaro §5.4.2).
A leader CANNOT commit an entry from an EARLIER term just because a majority of nodes have it. Doing so can lead to a committed entry being overwritten by a later leader.
The scenario
Five servers, S1..S5. The log shows term numbers per entry slot:
Time t1: S1 (leader, term 2) replicates entry e@term2 to S2
S1's log: [e@t2] S2's log: [e@t2]
NOT yet on a majority (3 of 5).
Time t2: S1 crashes. S5 wins term 3 (its log was empty; majority of empty/short logs).
S5 appends f@t3. S5's log: [f@t3]
Time t3: S5 crashes before replicating. S1 recovers, wins term 4.
S1's log is [e@t2]. It replicates e@t2 to S3, getting majority (S1,S2,S3).
If S1 commits e@t2 now (based purely on replica count), it's COMMITTED.
Time t4: S1 crashes. S5 recovers, still has [f@t3]. S5 wins term 5
(some nodes haven't seen e@t2 OR S5's log is more recent in another scenario).
S5 overwrites e@t2 with f@t3 across the cluster.
The "committed" entry is GONE.
The rule
A leader may commit an entry by replica count ONLY if that entry is from the leader's CURRENT term. Entries from prior terms are committed TRANSITIVELY — only when a new entry from the current term reaches majority above them.
In code
def can_commit(entry_idx, entry_term, leader_term, replica_count, cluster_size):
if replica_count <= cluster_size // 2:
return False # not a majority
if entry_term != leader_term:
return False # Figure-8 — prior term, not safe
return True
To "force" old entries to commit, the leader appends a NO-OP entry at startup. As soon as the NO-OP is committed, everything before it is implicitly committed.
This is exactly what etcd does on every leader transition.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…