This is a naive implementation of the raft algorithm in Golang for learning purpose. This is a Work In Progress state.
To run a single node:
go run .
To run multiple nodes and monitor the logs:
./raft-nodes-start.shAnd after a moment kill the script and look at the logs on raft-combined.log.out
All writes must go through the leader.
{
"command": "SET X 10",
"serial_number": "1"
}-
Send request to any node
-
If not leader → you get:
{ "success": false, "leader_id": "node1" } -
Retry on leader
-
Leader:
- appends log
- replicates to quorum
- commits
- applies to state machine
{
"success": true
}Reads must also go through the leader.
{
"command": "GET X"
}-
Send request
-
If not leader → redirect
-
Leader:
- sends heartbeat (safety)
- reads from state machine
{
"status": true,
"value": "10"
}Both Submit and Get may return:
{
"success": false,
"leader_id": "node1"
}Client must retry on the leader.
Cluster changes use two-phase joint consensus.
{
"add_ids": ["node2"],
"add_nodes": {
"node2": "localhost:50052"
}
}{
"remove_ids": ["node2"]
}{
"add_ids": ["node3"],
"add_nodes": {
"node3": "localhost:50053"
},
"remove_ids": ["node2"]
}Phase 1 (Joint Config)
- Cluster enters
C_old,new - Both configs must agree (dual quorum)
Phase 2 (Final Config)
- New config committed
- Old nodes removed
- Cluster stabilizes
- Start cluster
- Wait for leader election
- Write:
{
"command": "SET Y 16",
"serial_number": "122"
}- Read:
{
"command": "GET Y"
}- Add node:
{
"add_ids": ["node2"],
"add_nodes": {
"node2": "localhost:50052"
}
}- Remove node:
{
"remove_ids": ["node2"]
}- Raft Paper: https://raft.github.io/raft.pdf