Simba π± is a custom implementation of Raft, tested with deterministic simulation.
A personal project. Raft runs inside a simulator where time, network and crashes are controlled, so every bug can be replayed exactly.
Overview
- Raft
- A consensus algorithm. A group of nodes agrees on one shared log, even if some crash or messages are delayed.
- Deterministic simulation testing
- The clock, the network and the failures are all controlled by the engine. The same seed always gives the same run.
- Matrix mode
- The simulated Simba π±: time is a counter and the network is a queue of events.
- Real mode
- The same Raft with real timeouts, disk and sockets. Only the interfaces change.
What is Raft?
Leader election
Every node is a follower, a candidate or the leader. A follower that stops hearing from the leader becomes a candidate and asks for votes. With a majority, it becomes the leader.
The leader sends heartbeats and replicates its log. An entry is committed once a majority has stored it.
How Simba π± runs Raft
One Raft, two modes
Raft never touches time, storage or the network directly. It uses interfaces. Matrix mode plugs in simulated versions and Real mode plugs in the real ones.
Every node is just a struct with its own state. The engine moves them forward.
Deterministic simulation testing
- What is it?
- Run the whole system inside a simulation where everything that could be random is driven by one seed.
- Why?
- Distributed bugs are rare and hard to reproduce. With a seed, a failing run can be replayed exactly, as many times as needed.
- Fast
- Time is not real, so hours of cluster life run in seconds. The limit is your CPU.
A time machine for your cluster
There is no real clock and no real network. Simba π± never waits for a timeout or a packet: it just moves the counter forward.
So the only limit is how fast your CPU can run the loop. Days of cluster life fit in a few seconds, and every run can be replayed with its seed.
MatrixChecker
Thousands of seeds, looking for one bug
An internal tool. It takes many seeds, runs the simulation with each one at different fuzz levels, and watches Raft the whole time.
Raft is full of assertions: rules that must always be true. The moment one is broken, the run panics. That seed is a bug, and it can be replayed exactly.
one leader per termcommitted entries never changelogs match on the same index and term
Time
Time is an integer
There is no system clock. The engine is a loop that adds one to a counter. Timeouts are just βwake me at tick Nβ.
Network
The network is a queue of events
Nodes never call each other. A message is an event with a sender, a receiver and a delivery tick. The engine delivers it when time gets there.
The latency is simulated: each message gets a random delay drawn from probabilities set by the fuzz level.
Fault injection
The fuzz level decides how often things go wrong. Same seed, same faults.
Latency
A message takes some ticks to arrive. Sometimes few, sometimes many.
Duplication
The network delivers the same message twice. Raft must handle it.
Message loss
The message disappears in the network and never arrives.
Node crash
A node goes down, drops messages, and later comes back to life.
Contact
Questions, ideas, suggestions or business inquiries? Write to me at this email, or open an issue on GitHub.