“CAP 定理的实际价值在于强迫设计者把"分区期间的行为"写进服务规格:拒绝哪些请求、降级到什么语义、愈合后如何收敛,都不再能含糊其辞。它解释了为什么基于多数派的共识与状态机复制系统在失去 q…”
形式陈述
将服务建模为确定性状态机
并固定初始状态
完整服务语义还要固定客户请求标识、重试去重、命令何时视为提交、何时可对客户响应,以及快照恢复和成员重配置如何与日志连接。若要对外提供线性一致的读,还需额外的读取协议;“日志相同”本身不是完整的端到端规格。
直觉
与其不断同步整个状态,状态机复制让排序层先提供共同命令前缀,再由各副本在本地重放同一计算。它由此把“多台副本如何保持一致”分成两层:共识或原子广播负责决定顺序,执行层让确定性状态机从相同初态按该顺序运行。仅仅复制数据或周期同步快照不够;若命令顺序不同,即使每条命令本身合法,也可能得到不同状态。反过来,同一日志也无法消除执行过程中未被记录为输入的非确定性。
例子与边界
初始余额为 withdraw(12) 与 deposit(5) 若按不同顺序并带余额检查,会产生不同结果:先取款则取款失败、最终余额为
执行还必须保持确定性:读取系统时间、随机数或外部服务会引入非确定性,必须转化为已排序输入或通过协议协调。“多数副本存有某条日志”也不自动意味着客户端已看到线性一致结果;还需领导者提交规则、读取协议和会话处理。成员重配置必须纳入日志,并通过相交配置让安全证据跨成员视图延续,避免新旧配置各自决定冲突命令。
推论与应用
在最多
状态机提供确定性转移语义,复制日志提供共同命令前缀;Paxos、Raft与Viewstamped Replication是日志层的具体协议。状态机复制由此支撑高可用键值存储、配置服务、数据库元数据和区块链执行模型。
形式化验证可以把实现状态映射到“共同 committed 前缀 + 确定状态”的抽象机,并用精化关系说明选主、重试和快照等内部步骤不改变外部历史。模型检查适合在有限副本和有界状态下搜索不变式反例,协议特有的 ballot、term 或选举机制仍留在各协议页,本页只规定排序层到确定性执行层的接口。
对外实现线性一致性还依赖正确的请求应答边界、读路径与去重;快照和日志压缩则在不改变已执行命令历史含义的前提下降低恢复成本。
从三份日志到一次成功响应
固定A、B、C三个非拜占庭副本,沿用Raft的稳定任期、日志与多数提交规则。业务是初值100的整数余额,add(d)返回更新后的余额;本段先把每个请求当成唯一一次逻辑操作。客户端调用、leader接收、日志追加、多数持久确认、提交、应用、响应是不同事件,只有最后一项出现在客户端的完成历史里。
- 时刻1,客户P调用
add(10);A在当前任期5把它追加为索引11 - 时刻2,A与B的稳定日志含11,C仍到10;时刻3,A按当前任期多数规则提交11
- 时刻4,A按顺序应用11,余额110,保存输出110;时刻5,P收到成功响应110
- 时刻6,客户Q才调用
add(5);它被放到索引12,时刻7获得A、B多数并提交,时刻8应用得到115,时刻9返回115
成功历史的顺序见证是add(10)->110在add(5)->115之前。可把本例写操作的线性化点选在各自首次成为不可撤销已提交项的时刻3与7:都位于调用和响应之间,确定性应用给出相应返回值。副本C稍后才应用11、12不影响这个客户端历史,它在追赶前不能未经读协议就返回旧余额。
一般构造按首次有效业务命令的日志顺序排列操作。每次只应用已提交前缀,且响应在应用产生结果之后;若X已返回、Y才调用,则Y不可能占据X之前的已提交槽位。新leader继承已提交前缀,因而跨换主仍保持这个实时顺序。这个论证对读还不完整:日志读按其槽位取结果,绕过日志的读则需读屏障与ReadIndex补齐权限与应用证据。不可把任意leader本地读强行塞进上述写顺序。
失败轨迹、未知与逻辑请求边界
把第一段时刻5提前到“A只在本地稳定追加11”之后,A随后隔离,B、C可以合法选出新leader并覆盖这个未提交尾部。P已看到110,后续正确读却仍是100,就无法给已成功的加10找到一个保留效果的合法顺序;本地fsync不够。相反,11已经提交而成功响应丢失时,该逻辑操作可以仍处于pending,后来的合法读取看到110并不矛盾,历史completion应按需要保留它,而不是因超时就把它删除。
还有另一种错误:同一逻辑请求的两份尝试进入11和12,两项日志都正确提交并各加10。复制安全完全成立,但逻辑请求若只应代表一次加10,余额120就违约。会话与结果去重把两份尝试映到同一个逻辑操作;只有第一次有效应用改变余额,后面的槽位只推进应用位置并重发原结果。该逻辑调用区间从第一次发起延续到最终取到对应结果,超时重试不是未经说明的新业务调用;若API选择每次重试都算新调用,所声明的规格就不同。
因此客户端观察到某次尝试成功与服务保证“一个逻辑请求一次效果”不能混淆。持久身份、结果保留、会话过期与恢复协议决定后者成立多久、哪些请求可以安全续试。确定性状态机也只能约束自己的原子域;对外发消息应记录为事务发件箱意图,再单独报告外部效果的确认状态。
状态、位置与结果的统一恢复
对已应用位置a,服务恢复状态应是同一已提交前缀的业务状态、请求结果表和应用索引。只恢复余额却丢去重,或只恢复位置却漏业务,都可能在一次重试后破坏刚才的历史映射。快照安装把截点索引/任期、结果表和配置一并发布;联合配置让提交证据跨成员变更继承。固定配置证明不自动涵盖这两项机制。
完整服务任务要求逐项填出三副本日志、commitIndex、lastApplied、业务结果与客户端知识;其检查器只复算有限事件,不替代本页的历史构造或Raft安全证明。
参考资料
- Fred B. Schneider, “Implementing Fault-Tolerant Services Using the State Machine Approach,” 1990.
- Leslie Lamport, “The Part-Time Parliament,” 1998.