#raft #distributed-systems #ha

riteraft

RiteRaft - 为普通人提供的 raft 框架

1 个不稳定版本

0.1.0 2023年7月26日

#8 in #ha

MIT/Apache

40KB
910 行代码

RiteRaft - 为普通人提供的 raft 框架

这是在 tikv/raft-rs 的基础上创建一个易于使用和实现的层的尝试。这不是最具功能性的 raft,而是一个方便的接口,可以快速开始,并很快拥有一个可工作的 raft。

该接口强烈受到 canonical/raft 的启发。

入门

为了“raft”存储,我们需要为它实现 Storage trait。以下是一个使用 HashStore 的示例,它是 HashMap 的线程安全包装器。

/// convienient data structure to pass Message in the raft
#[derive(Serialize, Deserialize)]
pub enum Message {
    Insert { key: u64, value: String },
}

#[derive(Clone)]
struct HashStore(Arc<RwLock<HashMap<u64, String>>>);

impl Store for HashStore {
    type Error = RaftError;

    fn apply(&mut self, message: &[u8]) -> Result<Vec<u8>, Self::Error> {
        let message: Message = deserialize(message).unwrap();
        let message: Vec<u8> = match message {
            Message::Insert { key, value } => {

                let mut db = self.0.write().unwrap();
                db.insert(key, value.clone());
                serialize(&value).unwrap()
            }
        };
        Ok(message)
    }

    fn snapshot(&self) -> Vec<u8> {
        serialize(&self.0.read().unwrap().clone()).unwrap()
    }

    fn restore(&mut self, snapshot: &[u8]) -> Result<(), Self::Error> {
        let new: HashMap<u64, String> = deserialize(snapshot).unwrap();
        let mut db = self.0.write().unwrap();
        let _ = std::mem::replace(&mut *db, new);
        Ok(())
    }
}

Store 只需要实现 3 个方法

  • Store::apply:将已提交的条目应用到存储中。
  • Store::snapshot:返回存储的快照数据。
  • Store::restore:应用作为参数传递的快照。

运行 raft

#[tokio::main]
fn main() {
    let store = HashStore::new();

    let raft = Raft::new(options.raft_addr, store.clone());
    let mailbox = Arc::new(raft.mailbox());
    let (raft_handle, mailbox) = match options.peer_addr {
        Some(addr) => {
            info!("running in follower mode");
            let handle = tokio::spawn(raft.join(addr));
            (handle, mailbox)
        }
        None => {
            info!("running in leader mode");
            let handle =  tokio::spawn(raft.lead());
            (handle, mailbox)
        }
    };

    tokio::join!(raft);
}

mailbox 为您提供与 raft 交互的方式,例如发送消息或将集群从集群中移除。

致谢

这项工作基于 raft-frp,但对代码进行了更多调整和改进。

许可证

本库根据您的选择许可为以下之一

依赖

~8–18MB
~219K SLoC