3个不稳定版本

0.3.0 2021年8月10日
0.2.1 2021年4月18日
0.2.0 2021年4月17日

#分布式系统中排名4

Download history 5/week @ 2024-03-09 1/week @ 2024-03-16 17/week @ 2024-03-30 2/week @ 2024-04-06 3/week @ 2024-04-13 11/week @ 2024-04-20 1/week @ 2024-04-27 32/week @ 2024-05-11 5/week @ 2024-05-18 2/week @ 2024-05-25 14/week @ 2024-06-01 56/week @ 2024-06-08 80/week @ 2024-06-15 6/week @ 2024-06-22

每月下载量156
用于集群模式

MIT许可MIT

40KB
832 代码行

Build Crates.io MIT licensed

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