外观
分布式系统自测与设计复盘
用纸笔画消息与持久状态,比背诵术语更能发现理解中的空白。以下问题都应能给出一个具体执行历史。
机制自测
1. 超时后能告诉用户“操作肯定没发生”吗?
不能。可能请求没到,也可能已执行而回复丢失。应明确结果未知,并通过请求身份、查询接口或重试恢复结果。业务接口若承诺明确失败,必须有额外协议支持。
2. 五节点只剩两个能通信,为什么不能把多数改成两票?
网络另一侧可能仍有三个节点,两个分区各自按“看得见的节点”计算多数会同时选出有效 leader,丢失多数集合的交集性质。成员变化必须是协议事件。
3. 谁的日志更“新”:长度 12、末任期 3,还是长度 9、末任期 4?
后者。Raft 先比较最后条目的任期,只有任期相同时才比较长度。只比较长度会破坏 leader completeness。
4. 一条命令在三个副本上,是否一定可以成功回复?
还需判断这些确认是否属于当前有效领导权、是否满足当前任期提交规则,并等状态机产生对应结果。必须核对具体协议,不能只数数组长度。
5. 同一个请求两次进入日志,为何不一定执行两次?
日志层处理顺序,状态机层用请求身份去重。第二次应用可以直接返回第一次保存的结果。
6. 快照只保存 KV,不保存去重结果,会怎样?
快照恢复后客户端可能重试快照之前的操作,服务无法识别已执行请求,重复产生副作用。迁移 shard 时也有同类问题。
7. Raft 与 2PC 各解决什么?
Raft 为同一复制组建立共同决策序列;2PC 在事务参与者间协调统一提交或中止。可用 Raft 复制参与者或协调者,但单组共识不自动提供跨组事务。
一次完整设计练习
设计一个五节点复制计数服务。明确 add 的请求身份、返回语义和读取一致性;列出 term、vote、log、counter、去重表分别在哪里持久化。依次注入:请求丢失、回复丢失、leader 追加后宕机、提交后宕机、少数派隔离、恢复时旧消息到达。每个场景给出允许结果与禁止结果。
验收时不要只写“使用 Raft 所以安全”。应指出哪一个检查阻止哪一种错误,以及测试中如何观察。例如“投票前比较末任期,阻止缺少已提交前缀的候选者得到必要多数”;“去重表随日志回放,避免回复丢失后重试再次加一”。
与其他课程连接
OS 的日志恢复与分布式日志复制都关心“哪一刻可以承诺成功”,但一个面对本机崩溃,另一个还面对多节点消息。并行程序中的锁建立线程间顺序,分布式共识建立副本间命令顺序,代价和故障假设不同。数据库的事务隔离又在这些机制之上约束业务读写历史。把层次分开,才能准确组合。