Lesson 19 / 33

Committing Entries and the Current-Term Rule

Compute a leader's commit index from matchIndex and explain why only current-term entries are committed by counting.

By · 15 years in web development

When is an entry committed?

An entry is committed once the leader that created it has replicated it on a majority of servers. Committed entries are durable and will eventually be applied by every state machine. The leader tracks, for each follower, matchIndex, the highest index known to be replicated there. The commit index is then the largest N such that a majority have matchIndex >= N and log[N].term == currentTerm. That second condition matters. A new leader cannot conclude an entry from an older term is committed just because it now sits on a majority: the Raft paper's Figure 8 shows such an entry can still be overwritten by another leader. Instead, the leader commits an entry from its own term, and the Log Matching property commits everything before it indirectly. This is why a new leader immediately appends a no-op entry in its term: it quickly commits earlier entries and lets it learn its commit index.

Tracing the commit index calculation

The second call has entries replicated on a majority up to index 3, but entry 3 is from term 2 while the leader is in term 3.

def commit_index(match_index, leader_last, log_terms, current_term, old_commit):
    """Highest N replicated on a majority whose entry is from the current term."""
    indexes = sorted(match_index + [leader_last], reverse=True)
    majority_n = indexes[len(indexes) // 2]     # replicated on a majority
    for n in range(majority_n, old_commit, -1):
        if log_terms[n - 1] == current_term:
            return n
    return old_commit

terms = [1, 1, 2, 3, 3]            # term of entries 1..5
print(commit_index([5, 4, 2, 1], 5, terms, current_term=3, old_commit=2))
print(commit_index([3, 3, 1, 1], 5, terms, current_term=3, old_commit=2))

Output:

4
2
  1. Line 11: First call: matchIndex [5,4,2,1] plus leader 5. Majority reaches 4, and entry 4 is from term 3, so it returns 4.
  2. Line 12: Second call: followers have only reached 3, 3, 1 and 1.
  3. Line 3: Add the leader's own last index and sort descending.
  4. Line 4: The middle element (index 2, the third of five) is replicated on at least 3 of 5 servers.
  5. Line 5: Scan downward from 3 to just above the old commit index 2.
  6. Line 6: Entry 3 has term 2, not the current term 3, so it is not committed by counting.
  7. Line 8: No current-term entry qualifies, so the commit index stays at 2.

Ratifying old minutes

A newly elected chair does not declare last year's draft minutes approved just because most members have a copy. Instead they pass a fresh resolution in their own term that says 'the minutes up to this point stand', and that ratifies everything before it.

Quick check: Why does a new Raft leader often append a no-op entry immediately?

  • To reset all followers' logs
  • To measure network latency to followers
  • To trigger snapshotting
  • To commit an entry in its own term, which also commits all earlier entries
Answer

To commit an entry in its own term, which also commits all earlier entries — Earlier-term entries cannot be committed by counting replicas. Committing a current-term no-op commits everything before it through Log Matching.