raft-rust 0.1.0

Standalone Raft consensus library in Rust
Documentation

raft-rust

独立的 Raft 共识实现(Rust)。

  • step() / tick() 驱动的纯协议核心 + 可插拔存储 / 状态机
  • 部署:每个节点一份 YAML、一个进程(raft-node),节点间 TCP + bincode
  • 客户端raft-cli(put / get / scan / status / members)

不是生产级产品:无 TLS、快照整包发送、教学向实现。适合学习 Raft 与本地原型。

深入文档

想了解 从这读
选举 03
put 从从节点到存储 04
复制冲突 / 线性读 / Session 07 · 08 · 09
成员变更 / 快照 10 · 11
部署 / 故障 / FAQ 12 · 13 · 14

功能

能力 说明
共识 选主、日志复制、多数提交
领导者线性一致读(多数确认)
Pre-vote / CheckQuorum Options 可开关,减轻分区干扰
成员变更 联合共识(Joint Consensus)
领导转移 ChangeMembership 可去掉当前领导,Simple 提交后旧领导 step down
写去重 WriteSession(client_id, seq) + SessionState
快照 snapshot / InstallSnapshot / 日志 compact_to
存储 BitCask 日志结构引擎(data_dir/bitcask.log
网络 TCP 帧:WireMsg::{Raft, Client, ClientReply}
测试用进程内集群 cluster::Cluster(channel + 故障注入)

依赖

  • Rust(edition 2024)
  • 构建:cargo build --bins

单节点(最快上手)

配置里 peers: [](或不写同伴),进程启动后立刻成为 Leader

# 终端 1:节点

cargo run --bin raft-node -- --config config/single.yaml


# 终端 2:CLI(只连一个地址)

cargo run --bin raft-cli -- --peers 127.0.0.1:7001 status

cargo run --bin raft-cli -- --peers 127.0.0.1:7001 put a apple

cargo run --bin raft-cli -- --peers 127.0.0.1:7001 get a

cargo run --bin raft-cli -- --peers 127.0.0.1:7001 scan

config/single.yaml

node:
  id: 1
  listen: "127.0.0.1:7001"
  data_dir: "data/single"

peers: []

options:
  heartbeat_interval: 2
  election_timeout_min: 5
  election_timeout_max: 10
  max_append_entries: 100
  pre_vote: true
  check_quorum: true
  snapshot_threshold: 1000

数据目录:data/single/bitcask.log(已在 .gitignore 中忽略 data/)。

也可:cargo run -- --config config/single.yamldefault-run = raft-node)。


多节点(每节点一份配置)

三份配置、三个进程,例如 config/node1.yaml / node2.yaml / node3.yaml

# 三个终端分别启动

cargo run --bin raft-node -- --config config/node1.yaml

cargo run --bin raft-node -- --config config/node2.yaml

cargo run --bin raft-node -- --config config/node3.yaml


# CLI:可写多个 peer,失败/Abort 时换节点重试

cargo run --bin raft-cli -- --peers 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003 status

cargo run --bin raft-cli -- --peers 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003 put b banana

cargo run --bin raft-cli -- --peers 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003 get b

config/node1.yaml 示例:

node:
  id: 1
  listen: "127.0.0.1:7001"
  data_dir: "data/node1"

peers:
  - { id: 2, addr: "127.0.0.1:7002" }
  - { id: 3, addr: "127.0.0.1:7003" }

options:
  heartbeat_interval: 2
  election_timeout_min: 5
  election_timeout_max: 10
  max_append_entries: 100
  pre_vote: true
  check_quorum: true
  snapshot_threshold: 1000

节点 2、3 同理:改 id / listen / data_dirpeers 写另外两个地址。


raft-cli 命令

raft-cli --peers host:port[,host:port...] [--client-id UUID] <command>
命令 说明
put <key> <value> 带 session 的写(幂等序号)
get <key> 线性一致读
scan 扫描全部 KV
status 领导、term、commit、voters 等
members <id,id,...> 成员变更(目标投票集合)

客户端 session 文件

  • 路径:运行 CLI 时的当前工作目录下的 .raft-cli-session
  • 内容:client_id + last_seq(每次 put 递增)
  • 作用:超时重试同一写时带相同 (client_id, seq),避免双执行
  • 可用 --client-id <uuid> 覆盖 id;文件已在 .gitignore

这不是集群配置,也不是节点数据;删了只会让 CLI 当成新客户端重新编号。


配置字段

字段 含义
node.id 节点 ID(u8,集群内唯一)
node.listen 本机监听 ip:port
node.data_dir 数据目录(BitCask + 快照元数据)
peers 其它节点 { id, addr }空 = 单节点
options.heartbeat_interval 心跳间隔(tick)
options.election_timeout_min/max 选举超时范围(tick)
options.max_append_entries 单次 Append 最多条数
options.pre_vote 是否 Pre-vote
options.check_quorum 领导丢多数是否下台
options.snapshot_threshold 距上次快照 apply 多少条后压缩;0 关闭

逻辑时间:TICK_INTERVAL = 100ms。


测试

cargo build --bins    # 真多进程测试需要 raft-node 二进制

cargo test

覆盖范围包括:

  • 进程内:选主、转发、分区、杀主、丢包/乱序、并发客户端
  • Pre-vote / CheckQuorum
  • 成员变更、移除领导(领导转移)
  • Session 去重、BitCask
  • 重启恢复快照截断后重启
  • 真多进程tests/multi_process.rs 拉起子进程)

进程内演示(非部署路径):

cargo run --example kv_cluster


库内嵌入(可选)

use raft_rust::cluster::{wait_for_leader, Cluster};

let cluster = Cluster::spawn(&[1, 2, 3]); // 测试用进程内集群
let mut client = cluster.client();
wait_for_leader(&mut client)?;
client.put("k", "v")?;

或直接使用 Node + 自建传输(见 src/lib.rs / src/net)。


目录结构

src/
  bin/raft_node.rs     节点进程(单节点或多节点中的一员)
  bin/raft_cli.rs      命令行客户端
  net/                 TCP + bincode
  cluster/             进程内集群(测试 / example)
  config.rs            节点 YAML 加载
  raft/                协议:node / log / membership / session / kv
  storage/             Engine + BitCask
config/
  single.yaml          单节点
  node1.yaml … node3.yaml
tests/                 单元与集成测试
examples/kv_cluster.rs 进程内三节点演示

已知限制

  • 明文 TCP,无 TLS / 认证(生产可在前面做 TLS 终止)
  • 快照整包发送,不分块流式
  • 无自动领导优雅迁移 RPC(通过成员变更去掉旧领导实现 step down)
  • 非生产级运维能力(监控、动态配置热更新等未做)

许可证

Apache-2.0。实现紧贴 Raft 论文,并包含成员变更、Pre-vote、快照、多进程部署等扩展。