Raft Lite
Raft Lite is a very simple and understandable implementation of the Raft consensus algorithm. It is intended to be used as a learning tool for those who are interested in understanding how Raft works internally.
The core logic is in src/raft_protocol.rs, which is a event loop that handles all the application requests, Raft protocol messages and timer events.
You can find detailed explanation of Raft Lite in this blog post.

Usage
Add this to your Cargo.toml:
[dependencies]
raft-lite = "0.2.2"
To use it in your project, you can initialize a Raft instance with a RaftConfig. The way you interact with the Raft instance is to send messages to it and receive messages from it. The message type is Vec<u8>. The Raft protocol will guarantee the message delivery is in total order.
The following example shows how to use Raft Lite to achieve a single value consensus. The example is in examples/dinner.rs.
use raft_lite::config::{RaftConfig, RaftParams};
use raft_lite::persister::AsyncFilePersister;
use raft_lite::raft::Raft;
use std::path::PathBuf;
#[tokio::main]
async fn main() {
let guests = vec![
"localhost:10624".to_string(),
"localhost:10625".to_string(),
"localhost:10626".to_string(),
];
let dinner_options = vec![
b"Ratskeller".to_vec(),
b"Pizzeria Ristorante Lachoni".to_vec(),
b"KFC".to_vec(),
];
for i in 0..guests.len() {
let guests = guests.clone();
let dinner_options = dinner_options.clone();
tokio::spawn(async move {
let mut raft = get_raft_instance(guests.clone(), guests[i].clone());
let (raft_broadcast_tx, mut raft_receive_rx) = raft.run();
let place = dinner_options[i].clone();
raft_broadcast_tx.send(place).await.unwrap();
let mut count = 0;
loop {
let msg = raft_receive_rx.recv().await.unwrap();
count += 1;
if count == 2 {
let final_decision = String::from_utf8(msg).unwrap();
println!("Guest {}: we'll have dinner at {}!", i, final_decision);
}
}
});
}
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
}
fn get_raft_instance(peers: Vec<String>, self_addr: String) -> Raft {
let path: PathBuf = PathBuf::from(format!("./data/dinner]/{self_addr}"));
let raft_config = RaftConfig::new(
peers.clone(),
self_addr.clone(),
RaftParams::default(),
Box::new(AsyncFilePersister::new(path)),
);
Raft::new(raft_config)
}
License
The project is under MIT license.
Related Projects
TODO