Raft implementation in Rust and Golang as a learning project
Vineed Kaladharan
Status:
π’ In Progress
π Basic state machine π’ In Progress
- Implementation of core state machine that processes and applies commands
- Handles read/write operations and maintains consistent state
- Ensures atomic execution of commands
β³ Term management
- Implementation of logical clock using term numbers
- Handling term updates and comparisons
- Term-based leader election protocol
β³ Log storage
- Persistent storage of log entries
- Log entry format with term numbers and commands
- Log consistency checking mechanisms
β³ State transitions
- Implementation of state persistence
- Safe state transfer between nodes
- Crash recovery handling
β³ Role transitions (Follower β Candidate β Leader)
- Election timeout management
- Vote request and response handling
- Leader heartbeat implementation
- Role-specific behavior implementation
Status:
βͺ Planned
- Node communication setup
- Leader election implementation
- Basic log replication
- Simple membership management
- Message passing infrastructure
Status:
βͺ Planned
- Complete log replication
- Snapshot handling
- Membership changes
- Recovery mechanisms
- Fault tolerance
- Created basic func to accept number of servers to run in random ports as async
π’ Done
- Added timeout on each servers at random milliseconds. When any one of the servers' gets timed out, it becomes 'Leader'. Rest of the nodes becomes 'Follower' using global concurrent variable
π’ Done
- Added func to generate random election timeout between 150-300ms
π’ Done
- Added func to generate random heartbeat timeout between 100-200ms
π’ Done
main() β createRaftCluster()
βββ For each server (concurrent):
β βββ NewRaftServer(id, port)
β β βββ Initialize RaftServer struct
β β βββ Set initial state as Follower
β βββ server.Start()
β βββ Start RPC server
β βββ resetElectionTimer()
Election Timer Expires
βββ State changes to Candidate
βββ Increment currentTerm
βββ Vote for self
βββ Send RequestVote RPCs to all peers
βββ If majority votes received:
βββ becomeLeader()
βββ Change state to Leader
βββ Cancel election timer
βββ startHeartbeat()
Leader's startHeartbeat()
βββ Create heartbeat timer (interval: 15ms)
βββ On timer tick:
βββ sendHeartbeats()
βββ For each peer:
β βββ Prepare HeartbeatArgs
β βββ Send Heartbeat RPC
βββ Handle responses:
βββ Update term if needed
βββ Step down if higher term seen
- Follower: Initial state of all servers
- Candidate: State during election process
- Leader: State after winning an election
- Election Timeout: Random duration between 150-300ms
- Heartbeat Interval: Fixed at 15ms
-
Leader Election
- Triggered by election timeout
- Requires majority votes to become leader
- Uses term numbers to maintain consistency
-
Heartbeat System
- Regular heartbeats from leader to maintain authority
- Prevents unnecessary elections
- Resets follower election timers
-
Term Management
- Monotonically increasing term numbers
- Used to detect stale leaders
- Helps maintain cluster consistency
The implementation uses Go's standard libraries:
net/rpc
for RPC communicationsync
for mutex and synchronizationtime
for timer management
RaftServer
: Main server structureRaftRPC
: RPC interface implementation- Various RPC argument and reply structures for voting and heartbeat mechanisms
To start a Raft cluster:
cd goraft
go run main.go -n <number_of_servers>
Default number of servers is 3 if not specified.
2024/11/26 14:17:17 Creating Raft cluster with 5 servers...
2024/11/26 14:17:17 Server 1 started on port 52000 as Follower
2024/11/26 14:17:17 Server 4 started on port 52003 as Follower
2024/11/26 14:17:17 Started Raft server 1 on port 52000
2024/11/26 14:17:17 Server 3 started on port 52002 as Follower
2024/11/26 14:17:17 Server 5 started on port 52004 as Follower
2024/11/26 14:17:17 Started Raft server 5 on port 52004
2024/11/26 14:17:17 Server 2 started on port 52001 as Follower
2024/11/26 14:17:17 Started Raft server 4 on port 52003
2024/11/26 14:17:17 Started Raft server 3 on port 52002
2024/11/26 14:17:17 Started Raft server 2 on port 52001
2024/11/26 14:17:17 Server 5: Yay, I am first! Becoming Leader
2024/11/26 14:17:17 Server 3: Another leader was elected, becoming Follower
2024/11/26 14:17:18 Server 2: Another leader was elected, becoming Follower
2024/11/26 14:17:18 Server 4: Another leader was elected, becoming Follower
2024/11/26 14:17:18 Server 1: Another leader was elected, becoming Follower
2024/11/26 14:17:32 Sending: are you alive? id: 5
2024/11/26 14:17:32 Received: are you alive? id: 5
2024/11/26 14:17:32 Sending: yes i am alive, id: 1
2024/11/26 14:17:32 Received: yes i am alive from server at port 52000
2024/11/26 14:17:32 Received: are you alive? id: 5
2024/11/26 14:17:32 Sending: yes i am alive, id: 2
2024/11/26 14:17:32 Received: yes i am alive from server at port 52001
2024/11/26 14:17:32 Received: are you alive? id: 5
2024/11/26 14:17:32 Sending: yes i am alive, id: 3
2024/11/26 14:17:32 Received: yes i am alive from server at port 52002
2024/11/26 14:17:32 Received: are you alive? id: 5
2024/11/26 14:17:32 Sending: yes i am alive, id: 4
2024/11/26 14:17:32 Received: yes i am alive from server at port 52003
2024/11/26 14:17:33 Server 2: Another leader was elected, becoming Follower
2024/11/26 14:17:33 Server 3: Another leader was elected, becoming Follower
2024/11/26 14:17:33 Server 4: Another leader was elected, becoming Follower
2024/11/26 14:17:33 Server 1: Another leader was elected, becoming Follower
2024/11/26 14:17:40 Shutting down Raft cluster...
2024/11/26 14:17:40 rpc.Serve: accept:accept tcp 127.0.0.1:52000: use of closed network connection
2024/11/26 14:17:40 rpc.Serve: accept:accept tcp 127.0.0.1:52001: use of closed network connection
2024/11/26 14:17:40 rpc.Serve: accept:accept tcp 127.0.0.1:52002: use of closed network connection
2024/11/26 14:17:40 rpc.Serve: accept:accept tcp 127.0.0.1:52003: use of closed network connection
2024/11/26 14:17:40 rpc.Serve: accept:accept tcp 127.0.0.1:52004: use of closed network connection
2024/11/26 14:17:41 Raft cluster shutdown complete.
RawNode::new(config, storage, logger)
βββ Create Raft instance
β βββ Initialize ProgressTracker
β βββ Setup RaftLog with storage
β βββ Set initial state as Follower
βββ Load initial state
β βββ Load HardState if exists
β βββ Apply committed entries
βββ Start election timer
Election Timer Expires
βββ Increment term
βββ Change state to Candidate
βββ Vote for self
βββ Send RequestVote RPCs
β βββ Include last log index/term
β βββ Wait for responses
βββ If majority votes received:
βββ Change state to Leader
βββ Initialize volatile leader state
βββ Start sending heartbeats
Leader's tick_heartbeat()
βββ Increment heartbeat counter
βββ If heartbeat_elapsed >= timeout:
β βββ Reset heartbeat timer
β βββ Send MsgBeat to self
β βββ Broadcast heartbeats to followers
βββ Handle responses:
βββ Update progress
βββ Check term
βββ Step down if higher term seen
RawNode
: Main interface for external interactionRaft
: Core consensus logic implementationStorage
: Interface for persistent stateProgressTracker
: Tracks peer progress and voting
- Heartbeat Tick: Every 3 ticks
- Election Tick: 10 ticks
- Base Tick: 100ms (configurable)
-
Volatile State
- Current term
- Vote history
- Log entries
-
Persistent State
- Hard state (term, vote, commit)
- Log entries
- Snapshot metadata
To start a Raft cluster:
cd rustyraft
cargo run
The implementation supports:
- Custom storage backends
- Configurable timeouts
- Snapshot and log compaction
- Leader election and transfer
- Dynamic membership changes
[2024-11-26T10:24:12Z INFO rustyraft] Starting Raft cluster with 5 servers...
[2024-11-26T10:24:12Z INFO rustyraft] Server 2 starting on port 8002 with timeout 3000ms
[2024-11-26T10:24:12Z INFO rustyraft] Server 3 starting on port 8003 with timeout 3000ms
[2024-11-26T10:24:12Z INFO rustyraft] Server 0 starting on port 8000 with timeout 3000ms
[2024-11-26T10:24:12Z INFO rustyraft] Server 1 starting on port 8001 with timeout 3000ms
[2024-11-26T10:24:12Z INFO rustyraft] Server 4 starting on port 8004 with timeout 3000ms
[2024-11-26T10:24:16Z INFO rustyraft] Server 1 timed out and became Leader
[2024-11-26T10:24:16Z INFO rustyraft] Server 4 received heartbeat from Leader 1
[2024-11-26T10:24:16Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:16Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:16Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:17Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:17Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:17Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:17Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:19Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:19Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:19Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:19Z INFO rustyraft] Server 4 received heartbeat from Leader 1
[2024-11-26T10:24:20Z INFO rustyraft] Server 4 received heartbeat from Leader 1
[2024-11-26T10:24:20Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:20Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:20Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:22Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:22Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:22Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:22Z INFO rustyraft] Server 4 received heartbeat from Leader 1
[2024-11-26T10:24:23Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:23Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:23Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:23Z INFO rustyraft] Server 4 received heartbeat from Leader 1
[2024-11-26T10:24:25Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:25Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:25Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:25Z INFO rustyraft] Server 4 received heartbeat from Leader 1
[2024-11-26T10:24:26Z INFO rustyraft] Server 3 received heartbeat from Leader 1
[2024-11-26T10:24:26Z INFO rustyraft] Server 2 received heartbeat from Leader 1
[2024-11-26T10:24:26Z INFO rustyraft] Server 0 received heartbeat from Leader 1
[2024-11-26T10:24:26Z INFO rustyraft] Server 4 received heartbeat from Leader 1