Cluster Formation
A Raft
node enters Learner
state when it is created by Raft::new()
.
To form a cluster, application must call Raft::initialize(membership)
.
Raft::initialize()
This method will:
-
Append one membership log at index 0, the log id has to be
(leader_id=(0,0), index=0)
. The membership will take effect at once. -
Enter Candidate state and start vote to become leader.
-
The leader will commit a blank log to commit all preceding logs.
Errors and failures
-
Calling this method on an already initialized node just returns an error and is safe, i.e.
last_log_id
on this node is not None, orvote
on this node is not(0,0)
. -
Calling this method on more than one node at the same time:
-
with the same
membership
, it is safe. Because voting protocol guarantees consistency. -
with different
membership
it is ILLEGAL and will result in an undefined state, AKA the split-brain state.
-
Conditions for initialization
The conditions for a legal initialization is as the above because:
The first membership log with log id (vote, index=0)
will be appended to initialize a node, without consensus.
This has not to break the commit condition:
-
Log id
(vote, index=0)
must not be greater than any committed log id. ifvote
is not the smallest value, i.e.(term=0, node_id=0)
, it has chance to be greater than some committed log id. This is why the first log has to be the smallest:((term=0, node_id=0), 0)
. -
And a node should not append a log that is smaller than its
vote
. Otherwise, it is actually changing the history other nodes has seen. This has chance to (but not certainly will) break the consensus, depending on the protocol. E.g. if the cluster has been running a fast-paxos like protocol, appending a smaller log thanvote
is illegal. By not allowing to append a smaller log thanvote
, it will always be safe.
From these two reason, it is only allowed to append the first log if:
vote==(0,0)
. And this is why the initial value of vote
has to be (0,0)
.