#分布式共识 #raft-共识 #raft #共识 #分布式系统

little_raft

最轻量级的分布式共识库。运行您自己的复制状态机!

7 个版本

0.2.0 2022 年 1 月 8 日
0.1.6 2021 年 12 月 1 日
0.1.4 2021 年 11 月 20 日
0.1.3 2021 年 8 月 21 日

#564 in 并发

每月 22 次下载

MIT 许可证

50KB
875

Little Raft

最轻量级的分布式共识库。运行您自己的复制状态机!❤️

安装

只需导入 crate。在您的 Cargo.toml 中添加

[dependencies]
little_raft = "0.1"

使用

要启动 Little Raft,您只需做三件事。

  1. 实现您集群想要维护的 StateMachine。Little Raft 将负责在集群中复制此机器并就其状态达成共识。
/// StateMachine describes a user-defined state machine that is replicated
/// across the cluster. Raft can Replica whatever distributed state machine can
/// implement this trait.
pub trait StateMachine<T>
where
    T: StateMachineTransition,
{
    /// This is a hook that the local Replica will call each time the state of a
    /// particular transition changes. It is up to the user what to do with that
    /// information.
    fn register_transition_state(&mut self, transition_id: T::TransitionID, state: TransitionState);

    /// When a particular transition is ready to be applied, the Replica will
    /// call apply_transition to apply said transition to the local state
    /// machine.
    fn apply_transition(&mut self, transition: T);

    /// This function is used to receive transitions from the user that need to
    /// be applied to the replicated state machine. Note that while all Replicas
    /// poll get_pending_transitions periodically, only the Leader Replica
    /// actually processes them. All other Replicas discard pending transitions.
    /// get_pending_transitions must not return the same transition twice.
    fn get_pending_transitions(&mut self) -> Vec<T>;
}
  1. 实现 Cluster 抽象,以便本地副本可以与其他节点通信。
/// Cluster is used for the local Raft Replica to communicate with the rest of
/// the Raft cluster. It is up to the user how to abstract that communication.
/// The Cluster trait also contains hooks which the Replica will use to inform
/// the crate user of state changes.
pub trait Cluster<T>
where
    T: StateMachineTransition,
{
    /// This function is used to deliver messages to target Replicas. The
    /// Replica will provide the to_id of the other Replica it's trying to send
    /// its message to and provide the message itself. The send_message
    /// implementation must not block but is allowed silently fail -- Raft
    /// exists to achieve consensus in spite of failures, after all.
    fn send_message(&mut self, to_id: usize, message: Message<T>);

    /// This function is used by the Replica to receive pending messages from
    /// the cluster. The receive_messages implementation must not block and must
    /// not return the same message more than once.
    fn receive_messages(&mut self) -> Vec<Message<T>>;

    /// By returning true from halt you can signal to the Replica that it should
    /// stop running.
    fn halt(&self) -> bool;

    /// This function is a hook that the Replica uses to inform the user of the
    /// Leader change. The leader_id is an Option<usize> because the Leader
    /// might be unknown for a period of time. Remember that only Leaders can
    /// process transitions submitted by the Raft users, so the leader_id can be
    /// used to redirect the requests from non-Leader nodes to the Leader node.
    fn register_leader(&mut self, leader_id: Option<ReplicaID>);
}
  1. 启动您的副本!
    /// Create a new Replica.
    ///
    /// id is the ID of this Replica within the cluster.
    ///
    /// peer_ids is a vector of IDs of all other Replicas in the cluster.
    ///
    /// cluster represents the abstraction the Replica uses to talk with other
    /// Replicas.
    ///
    /// state_machine is the state machine that Raft maintains.
    ///
    /// noop_transition is a transition that can be applied to the state machine
    /// multiple times with no effect.
    ///
    /// heartbeat_timeout defines how often the Leader Replica sends out
    /// heartbeat messages.
    ///
    /// election_timeout_range defines the election timeout interval. If the
    /// Replica gets no messages from the Leader before the timeout, it
    /// initiates an election.
    ///
    /// In practice, pick election_timeout_range to be 2-3x the value of
    /// heartbeat_timeout, depending on your particular use-case network latency
    /// and responsiveness needs. An election_timeout_range / heartbeat_timeout
    /// ratio that's too low might cause unwarranted re-elections in the
    /// cluster.
    pub fn new(
        id: ReplicaID,
        peer_ids: Vec<ReplicaID>,
        cluster: Arc<Mutex<C>>,
        state_machine: Arc<Mutex<S>>,
        noop_transition: T,
        heartbeat_timeout: Duration,
        election_timeout_range: (Duration, Duration),
    ) -> Replica<S, T, C>;

    /// This function starts the Replica and blocks forever.
    ///
    /// recv_msg is a channel on which the user must notify the Replica whenever
    /// new messages from the Cluster are available. The Replica will not poll
    /// for messages from the Cluster unless notified through recv_msg.
    ///
    /// recv_transition is a channel on which the user must notify the Replica
    /// whenever new transitions to be processed for the StateMachine are
    /// available. The Replica will not poll for pending transitions for the
    /// StateMachine unless notified through recv_transition.
    pub fn start(&mut self, recv_msg: Receiver<()>, recv_transition: Receiver<()>);

这样,您就可以开始了。我们正在编写示例,但到目前为止,您可以查看 little_raft/tests 目录和 https://docs.rs/little_raft/0.1.3/little_raft/ 中的文档。我们正在添加更多测试。

测试

运行 cargo test

贡献

欢迎贡献!请记住,这个库的一个目标是要尽可能小和简单。让我们保持 little_raft/src 中的代码在 1000 行以下。违反此规则的 PR 将被拒绝。

> cloc little_raft/src
       6 text files.
       6 unique files.                              
       0 files ignored.

github.com/AlDanial/cloc v 1.90  T=0.02 s (369.2 files/s, 56185.0 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Rust                             6             82            199            632
-------------------------------------------------------------------------------
SUM:                             6             82            199            632
-------------------------------------------------------------------------------

您随时可以挑选并处理这个项目中的任何开放问题。或者,如果您在使用此库的过程中遇到任何问题,可以提交新问题。

依赖项

~3.5MB
~54K SLoC