Skip to content

Raftor 使用

Raftorraftpp 的高层运行时入口,接口定义位于 include/raftpp/raftor/raftor.h

不需要自行处理 Ready 持久化顺序、消息发送和应用回调时,优先使用该接口。

Raftor 提供两个工厂方法:

auto raftor = raftpp::raftor::Raftor::Create(config, std::move(state_machine));
auto raftor = raftpp::raftor::Raftor::Create(
config,
std::move(state_machine),
storage,
std::move(transport)
);
  • 第一种:使用默认 WAL 存储和默认传输实现。
  • 第二种:注入自定义 WritableStorage 和传输,适用于测试或定制化集成场景。

默认传输由 RaftorConfig.transport_kind 决定:Capnp 打开网络监听,Noop 不打开 socket,仅适合无远端 peer 的单节点或测试。

初始化运行时,开始接收连接,但不阻塞当前线程。

进入阻塞式事件循环,直到 Stop() 被调用。

手动驱动一次事件循环,适合嵌入已有 reactor、game loop 或调度框架。

优雅停止节点。未完成的提案与读请求会以关闭错误结束。

Raftor 内部是单线程事件循环,以下接口线程安全:

  • Propose()
  • ProposeSync()
  • ProposeAsync()
  • ReadIndex()
  • ReadIndexSync()

业务线程可直接投递请求到 RAFT 事件循环,无需额外同步协议。

raftor->Propose("payload", [](raftpp::Result<std::string> result) {
if (!result) {
return;
}
});
auto result = raftor->ProposeSync("payload", std::chrono::milliseconds{5000});
auto future = raftor->ProposeAsync("payload");
auto result = future.get();

返回值来自状态机 Apply()ApplyResult.response

ReadIndex() 用来确认当前读取可以满足线性一致性要求。

raftor->ReadIndex("ctx", [](raftpp::Result<void> result) {
if (result) {
// 在这里读取状态机中的业务状态
}
});
  • ReadIndex() 不直接返回业务数据。
  • 读许可建立后,应用自行从状态机或业务存储中取值。
  • RaftorConfig.read_only_option 决定该路径采用的算法。

提交一个配置变更提案,把新节点加入集群。

提交一个配置变更提案,把指定节点移出集群。

提交一个内部 metadata 日志来更新已有成员的传输地址。该成员必须已经存在于当前 ConfState 中。

地址更新应用后同步更新 WAL 地址簿和传输层 peer。节点重启后,默认 WAL 从地址簿恢复 peer 地址。

发起领导权转移。这是 best-effort 操作;如果目标节点未追平或不可达,转移可能失败。

主动触发当前节点发起选举,主要用于测试或人工干预。

NodeStatus 提供以下观测字段:

  • id
  • role
  • term
  • leader_id
  • commit_index
  • applied_index
  • pending_proposals

常用接口:

  • GetStatus()
  • IsLeader()
  • GetLeaderId()
  • IsRunning()

TakeSnapshot() 会主动触发一次快照流程。

长期运行场景通常通过 RaftorConfig 快照阈值自动触发。

节点启动时,如果存储中存在本地快照,Raftor::Create() 先恢复到状态机,再以快照 index 作为 RawNode 的初始 applied index。

config.enable_entry_checksum = true 时,Raftor 校验提案 entry 的 checksum。发现 ChecksumMismatch 进入 terminal state,节点停止运行,后续 Start()、提案和读请求均返回该错误。

默认关闭,用于兼容旧 WAL 和滚动升级。

以下场景直接使用 RawNode

  • 必须自己控制 Ready 持久化与发送顺序。
  • 已经有一套现成的传输和存储框架,且不想适配到 Raftor 约定。
  • 需要对复制流程、批处理或推进时机做精细调优。