Skip to content

🐯 [错误处理] AppendLogs 失败后未停止后续处理 · rpc.go #119

@github-actions

Description

@github-actions

来自 #117 的架构级评审建议。不阻塞合入,仅供参考是否有更好的架构解法。

💡 [建议 · 错误处理] AppendLogs 失败后未停止后续处理 Raft/rpc.go:183

问题根因:follower 端 AppendEntries 中,AppendLogs 失败时仅 slog.Error 记录日志后继续执行 persistStateLocked、更新 commitIndexapplyCommittedLogs——WAL 写入失败意味着数据未持久化,继续应用日志会提交尚未持久化的 entry,崩溃重启后这些 entry 丢失,造成已提交日志的回滚(违背 Raft 持久化保证)。

为什么低级解法不够:简单的修复是 return err——但这会让 follower 返回 RPC error,leader 会认为 follower 失败然后重试,行为基本正确但 error propagation 不优雅。更深层的问题是:WAL 写入失败是致命的,follower 应该 panic 或转为 passive 状态(至少不应继续参与 consensus),而不是安静地吃掉错误。

架构级方案:将 WAL 写入定义为错误不可恢复路径AppendLogs 失败时,follower 应 (a) 立即返回 RPC error 拒绝本次 AppendEntries(让 leader 重试),(b) 将该节点标记为"WAL 故障"状态,停止接受后续日志直到故障恢复。更激进的做法是直接 slog.Error + panic (类似 etcd 的做法),因为 Raft 的正确性依赖于持久化存储的正确性。本 PR 可先完成最小修复——让 AppendLogs 失败后返回 error,不做后续持久化。

代价/收益:直接 panic 适合 etcd 这样的生产级实现(fail-fast),代价是进程重启成本高;返回 RPC error 让 leader 重试更宽容,代价是错误路径的编程复杂度。建议本 PR 至少做到返回 error 并中止后续流程。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions