3个不稳定版本
0.3.0 | 2021年8月10日 |
---|---|
0.2.1 | 2021年4月18日 |
0.2.0 | 2021年4月17日 |
在#分布式系统中排名4
每月下载量156
用于集群模式
40KB
832 代码行
almost-raft
在分布式系统中,达成共识或对某些值达成一致是一个基本问题。虽然像Paxos这样的算法已经存在很长时间了,但它们的复杂性使得实现变得复杂。
因此,Raft被设计出来,在保持算法可理解的同时解决该问题。
Raft通过以下两个步骤来解决问题:
- 领导者选举 - 在启动时或现有领导者失败时选举一个节点作为领导者
- 日志复制 - 维护节点间的日志一致性
更多关于Raft的信息请访问 https://raft.github.io.
为什么是almost-raft
已经有由tikv的优秀人员实现的Raft在Rust中的实现。如果需要完整的Raft,请查看 tikv/raft-rs.
almost-raft 的编写考虑了以下几点:
- 个人需求,当然
- 极简主义
- 将节点间通信机制卸载到实现包中
- 用户不需要了解或关心Raft的内部工作原理
almost-raft 仅处理算法的第一步,即选举,因此得名。日志复制等由开发者自行处理。
使用方法
almost-raft 使用闭环,唯一的通信方式是使用mpsc通道和控制消息。
第一步是实现 trait Node
。例如 - 一个简单的节点,使用mpsc通道与其他节点通信
use tokio::sync::mpsc::Sender;
use almost_raft::{Message, Node};
#[derive(Debug, Clone)]
struct NodeMPSC {
id: String,
sender: Sender<Message<NodeMPSC>>,
}
#[async_trait]
impl Node for NodeMPSC {
type NodeType = NodeMPSC;
async fn send_message(&self, msg: Message<Self::NodeType>) {
self.sender.send(msg).await;
}
fn node_id(&self) -> &String {
&self.id
}
}
初始化 RaftElectionState
let (heartbeat_interval, message_timeout, timeout, max_node, min_node) =
(1000, 20, 5000, 5, 3);
let (tx, mut from_raft) = mpsc::channel(10);
let self_id = uuid::Uuid::new_v4().to_string();
let nodes = vec![]; // we'll add node later
let (state, tx_to_raft) = RaftElectionState::init(
self_id,
timeout,
heartbeat_interval,
message_timeout,
nodes,
tx.clone(),
max_node,
min_node,
);
现在我们可以使用 state
开始选举过程。但这并不一定会启动选举,它将等待直到有足够的节点 (min_node
)。
tokio::spawn(raft_election(state));
让我们添加节点
let (tx,rx) = mpsc::channel(10);
tx_to_raft
.send(Message::ControlAddNode(NodeMPSC {
id: uuid::Uuid::new_v4().to_string(),
sender: tx,
}))
.await;
Raft将通过mpsc通道通知任何领导权的变更。要接收事件
// let (tx, mut from_raft) = mpsc::channel(10);
// tx was used to initialize RaftElectionState
from_raft.recv().await;
依赖项
~3.5–5.5MB
~92K SLoC