How the Raft Consensus Algorithm Works in Distributed Systems
The Raft consensus algorithm is a leader-based replication protocol that enables distributed systems to maintain a consistent replicated log by separating consensus into three core sub-problems: leader election, log replication, and safety guarantees.
The Raft consensus algorithm provides a foundation for building highly available distributed services by ensuring that a cluster of servers presents a single logical state machine to clients, even when individual nodes crash or network partitions occur. According to the Snailclimb/JavaGuide repository's detailed documentation in docs/distributed-system/protocol/raft-algorithm.md, Raft deliberately simplifies consensus through clear role separation and deterministic state transitions. This guide examines the algorithm's mechanics, from node roles to log replication, based on the repository's authoritative technical analysis.
Core Architecture and Node Roles
Leader, Follower, and Candidate States
Every node in a Raft cluster maintains one of three distinct roles defined in the JavaGuide documentation. The Leader receives all client commands, appends them to its log, and replicates entries to followers via periodic heartbeat messages (implemented as AppendEntries RPCs). Followers passively receive these heartbeats and log entries, while also participating in elections by granting votes to candidates. When a follower times out without receiving valid heartbeats, it transitions to the Candidate state and initiates a new election by issuing RequestVote RPCs.
Terms and Logical Clocks
Raft organizes time into terms—monotonically increasing integers that act as logical clocks for election cycles. Each RPC message carries the sender's current term, and any node discovering a higher term immediately steps down to follower status. This mechanism guarantees that at most one leader exists per term, preventing split-brain scenarios while ensuring progress.
Leader Election Process
When a follower fails to receive heartbeats within a randomized election timeout, it increments its term and becomes a candidate. The election process follows these strict rules as documented in the JavaGuide source:
- Vote Request: The candidate sends
RequestVoteRPCs to all peers, including its last log index and term. - Voting Constraints: Nodes grant votes only if they haven't voted in the current term and the candidate's log is at least as up-to-date as their own (determined by comparing last log term, then index).
- Majority Victory: A candidate becomes leader upon receiving votes from a majority (
N/2 + 1) of nodes. - Safety Reversion: If a candidate encounters a higher term during the process, it immediately reverts to follower.
The randomized timeout intervals ensure that simultaneous candidacy remains statistically unlikely, providing liveness without compromising safety.
Log Replication Mechanism
Once elected, the leader handles all client requests through a structured replication flow:
AppendEntries RPC: The leader sends new log entries to followers along with prevLogIndex and prevLogTerm parameters. These serve as consistency checkpoints—followers accept new entries only if their existing log matches these previous coordinates exactly.
Backtracking Mechanism: When a follower rejects an AppendEntries call due to log inconsistency, the leader decrements nextIndex for that follower and retries with earlier entries. This process continues until the logs align, ensuring the Log Matching Property: if two entries share the same index and term, they contain identical commands and all preceding entries match.
Commitment Rule: An entry becomes committed once the leader receives successful acknowledgments from a majority of nodes. The leader then applies the entry to its state machine and notifies followers of the updated commit index.
Safety Guarantees
The Raft consensus algorithm enforces three critical safety properties:
- Leader Completeness: A leader must contain all entries committed in previous terms. The voting rule enforces this by requiring candidates to possess logs at least as complete as the voter's log, ensuring no committed entry is ever overwritten.
- Log Matching: If two logs contain entries with identical indices and terms, the logs are identical in all preceding entries. This is maintained through the
AppendEntriesconsistency check described indocs/distributed-system/protocol/raft-algorithm.md. - Election Restriction: Only nodes with sufficiently up-to-date logs can win elections, preventing stale nodes from becoming leaders and truncating committed entries.
Raft Implementation Examples
The JavaGuide repository provides conceptual Java implementations modeling Raft's core functions. These illustrate the state management and message handling patterns found in production systems.
Node State Definition
enum Role { LEADER, FOLLOWER, CANDIDATE }
class RaftNode {
volatile Role role = Role.FOLLOWER;
volatile long currentTerm = 0;
volatile String votedFor = null;
List<LogEntry> log = new ArrayList<>();
// Heartbeat timer (election timeout)
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
}
Election Routine
void startElection() {
role = Role.CANDIDATE;
currentTerm++; // new term
votedFor = selfId;
int votes = 1; // vote for self
for (String peer : peers) {
asyncRpc(peer, new RequestVote(currentTerm, selfId,
lastLogIndex(), lastLogTerm()),
resp -> {
if (resp.term > currentTerm) {
currentTerm = resp.term;
role = Role.FOLLOWER;
} else if (resp.granted) {
votes++;
if (votes > peers.size() / 2 && role == Role.CANDIDATE) {
becomeLeader();
}
}
});
}
}
Log Replication Handler
boolean onAppendEntries(AppendEntries args) {
if (args.term < currentTerm) return false;
currentTerm = args.term;
role = Role.FOLLOWER; // step down if needed
// 1️⃣ consistency check
if (args.prevLogIndex > 0 &&
(log.size() < args.prevLogIndex ||
log.get(args.prevLogIndex-1).term != args.prevLogTerm)) {
return false; // reject, follower will backtrack
}
// 2️⃣ append new entries
for (LogEntry e : args.entries) {
if (log.size() >= e.index) {
// overwrite conflicting entry
log.set(e.index-1, e);
} else {
log.add(e);
}
}
// 3️⃣ update commit index
commitIndex = Math.min(args.leaderCommit, log.size());
return true;
}
Real-World Applications
Production systems leverage the Raft consensus algorithm for metadata management and distributed coordination. Apache Kafka uses KRaft mode to replace ZooKeeper with an internal Raft implementation for controller quorum management. etcd, the distributed key-value store backing Kubernetes, relies on Raft as its consensus core. The JavaGuide repository references Lu-Raft-KV, a Java teaching project implementing core Raft functions, listed in docs/open-source-project/practical-project.md for hands-on learning.
Summary
- The Raft consensus algorithm uses a strong leader model where only the leader accepts client writes and manages log replication.
- Terms provide logical clocks that prevent split-brain scenarios by forcing nodes to step down when encountering higher term values.
- Leader election requires majority votes and enforces log completeness constraints to ensure safety.
- Log replication uses
AppendEntriesRPCs with consistency checks to guarantee that committed entries are durable and identical across all nodes. - Production deployments include Kafka KRaft, etcd, and various educational implementations referenced in the Snailclimb/JavaGuide documentation.
Frequently Asked Questions
What is the difference between a Candidate and a Follower in Raft?
A Follower is a passive node that accepts log entries and heartbeats from the leader and votes in elections. A Candidate is a former follower that has timed out waiting for heartbeats, incremented its term, and initiated an election by requesting votes from peers. If the candidate fails to win a majority, it reverts to follower status.
How does Raft prevent multiple leaders from existing simultaneously?
Raft uses terms—monotonically increasing integers that act as logical clocks. Every RPC includes the sender's term, and nodes automatically step down to follower if they encounter a higher term. Since a candidate must win a majority vote to become leader, and majorities must overlap, at most one leader can exist per term.
What happens when a Raft node receives an AppendEntries RPC with conflicting log entries?
The node rejects the RPC if its log doesn't contain an entry matching prevLogIndex and prevLogTerm. The leader then decrements nextIndex for that follower and retries with earlier entries. This backtracking continues until the follower's log aligns with the leader's, at which point the follower overwrites any conflicting entries and appends new ones.
Where can I find the complete Raft algorithm explanation in the JavaGuide repository?
The authoritative documentation resides in docs/distributed-system/protocol/raft-algorithm.md, which covers roles, leader election, log replication, and safety proofs. Additional implementation references appear in docs/open-source-project/practical-project.md, including links to the Lu-Raft-KV teaching project.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →