依据:design-v2 §2、design-v3 §2.1 版本:v1.0 | 状态:开发就绪(M1 固定 openraft 版本后核对 trait 签名)
- 职责:openraft 实例组装(RaftTypeConfig/Storage/Network)、bootstrap、join/promote/remove、 快照与追赶、选举参数、leader 重定向信息。
- 不做:状态机业务逻辑(apply 委托 dsh-core);对外 API(dsh-api 提供 join 端点,本模块提供节点间 RPC client)。
pub type NodeId = u64; // 持久化 identity.json
pub struct Node { pub grpc_addr: String, pub http_addr: String, pub raft_addr: String }
pub struct RaftTypeConfig;
impl openraft::RaftTypeConfig for RaftTypeConfig {
type D = Node;
type R = openraft::raft::Entry<Command>;
type NodeId = NodeId;
type Node = Node;
}
pub async fn start(config: NodeConfig) -> Result<(Raft, JoinHandle)> {
let store = dsh_storage::open(&config.data_dir)?; // 模块 02
let state_machine = dsh_core::StateMachine::new(store); // 模块 01
let raft = Raft::new(config.node_id, config.raft_addr, log_store, sm_store, raft_config).await?;
if config.bootstrap { raft.initialize(vec![(node_id, node)]).await?; }
else if let Some(join) = &config.join { join_cluster(&raft, join).await?; }
Ok((raft, spawn_background(raft.clone())))
}
| 操作 | 入口 | 实现 |
|---|---|---|
| join | POST /api/v1/cluster/join(任意节点) | 转发 leader → add_learner(node_id, node) → 返回成员表 |
| promote | POST /api/v1/cluster/promote | change_membership([voters], false) |
| remove | POST /api/v1/cluster/remove | 先 change_membership 降级再移除 learner |
| 成员表 | ListMembers(gRPC)+ GET /api/v1/cluster/members | 从 raft.metrics() 派生 |
pub struct StateMachineStore {
pub sm: StateMachine, // dsh-core
pub storage: Arc<dyn Storage>, // 模块 02
}
// 实现 openraft::RaftStateMachine:
// - apply(entry):entry.data 反序列化为 Command → core.apply(cmd, now_ms)
// → 返回事件(由 dsh-watch 消费,模块 06)
// - get_snapshot / begin_receiving_snapshot / install_snapshot:经 rocksdb checkpoint
- 触发:--snapshot-interval(10k 条)/ --snapshot-size(64MB)。
- 追赶限速:--snapshot-limit(64MB/s);RaftNetwork 走 gRPC 流。
- 参数:heartbeat 500ms;election timeout 1500~3000ms;--read-mode(linear/stale):
- linear:读走 ReadIndex(ensure_linearizable)后本地读;写走 leader。
- stale:follower 本地读(可能稍旧但已提交)。
- leader 重定向:dsh-api 捕获 ForwardToLeader → ERR_LEADER_REDIRECT{leader_hint}。
- 错误:ErrorKind::Raft(选举失败/成员变更冲突),CLI 输出可读信息。
- 运维:dsh admin promote / remove-node / snapshot 映射到 §4 操作。
- RAFT-001/002/003/004:3 节点 kill/分区/join 追平/落后追赶——用 dsh-testkit 的 TestCluster(先进程内多 Raft,后进程级)。
- 成员变更期间脑裂防护验证(openraft 保证,测试确认)。
□ 固定 openraft 版本并核对 trait □ NodeId/Node/RaftTypeConfig □ StateMachineStore(apply/快照) □ RaftNetwork(gRPC) □ bootstrap/join/promote/remove □ 快照追赶限速 □ ReadIndex 线性读 □ 错误映射(ForwardToLeader) □ TestCluster 骨架(testkit) □ 集群测试 RAFT-001~004