Skip to content

因果关系、一致性与共识约束 ​

一致性模型、因果关系与逻辑时钟 ​

前置:能区分消息发送与接收、读写调用与返回,理解副本和网络分区;Python 3.10+ 仅用于离线时钟与日志推演。教学范围为Lamport1978;Gilbert/Lynch2002与2012回顾;Python 3.10+。核对日期2026-10-17。示例未执行,本轮没有安装依赖、生成协议代码、启动服务或浏览器预览。完整文件与输入见向量时钟输入及日志投票完整推演;推演结论只适用于写明的模型。

读法:先用两个副本 A、B 上的寄存器 x 串起“先后、并发、分区后能否成功读写”,再单独引入第三个副本 C 讨论多数集合;Raft 是另一组更强的日志协议约束,不能由向量时钟直接推出。

术语本文含义
操作历史每次读写的调用、返回和值,以及调用先后关系
因果先行进程内顺序或发送到接收的路径及其传递关系
并发事件之间没有已知因果路径,并非要求物理时间相同
R、W、N读集合大小、写集合大小、配置副本总数
termRaft 任期编号,用于选举和识别旧领导
matchIndex、commitIndex已确认复制的位置、已获协议允许提交的位置

一致性先描述什么历史 ​

一致性先描述什么历史:列出每次读写的调用、返回和值,再判断观察者可以看到哪些操作历史。线性一致要求存在尊重实时顺序的单一合法顺序,顺序一致只保留各进程程序顺序;“强一致”若没有明确模型,不能直接作为验收条件。例如 x 初值为 0,在 A 上写 x=1 已返回后才调用 B 上的读;线性一致的这次读不能成功返回旧值 0。

因果先后与并发 ​

因果先后与并发由进程内顺序和消息发送先于接收构成,再取传递闭包得到偏序。没有因果路径的事件可以并发,物理时钟显示先后并不能自动证明消息依赖。先画事件图,再谈时间戳编码,避免把数字大小直接当因果。

Lamport时钟单向保证 ​

Lamport时钟单向保证是因果先行蕴含逻辑时钟更小,逆命题不成立。两个无通信进程也可分别产生时钟1和2;由此不能判断谁影响谁。接收消息时令本地计数为max(本地,消息)+1,保证接收事件严格晚于发送。

事件图先于时间戳 ​

A 的发送与 B 的接收存在消息边,因此一定有因果先后;B 在接收前的本地事件与 A 的发送没有已知因果路径。即使两者物理时间不同,仍可在模型中并发。Lamport 时间只提供顺因果递增,不能用标量大小恢复图中所有边。

查看图表代码

来源与适用边界 ​

向量时钟、CAP与Raft安全约束 ​

向量时钟比较 ​

沿用 A、B 的事件:A 写 x=1 并发送消息 m,快照为 [1,0];B 尚未接收 m 时产生本地事件 [0,1]。这两个向量互有较大的分量,表示并发;B 接收 m 后逐分量取大再增加自身分量,得到 [1,2],它因果晚于 [1,0]。可对照同一输入的完整时钟推演。

向量时钟比较逐分量进行:所有分量不大于且至少一个严格小于表示先行,两方向都不成立表示并发。向量长度随参与者增长,动态成员与截断会影响语义;它记录因果知识,不会自行合并业务冲突或提供全局事务。

CAP分区推理 ​

CAP分区推理固定异步网络可分区及原子寄存器等假设。分区后一个节点确认新写,另一个无法获知;若仍必须对读给出满足寄存器语义的响应,就可能违背实时一致。这里的可用性不是月度SLO百分比,“三选二”会隐藏故障条件。

多数交集不等于完整协议 ​

多数交集不等于完整协议:R+W>N保证集合存在交集,但还需版本选择、失败写和并发顺序规则。只取最大时间戳可能受时钟漂移影响,法定人数公式不能单独证明线性一致。例如加入 C 后 N=3,写集合 {A,B} 与读集合 {B,C} 在 B 相交,R=W=2 满足 R+W>N;但若返回值选择和失败写规则不明确,存在交集仍不足以规定一次读应返回哪个版本。复制确认与客户端确认也需明确落盘和故障模型。

领导任期与投票约束 ​

领导任期与投票约束在Raft中共同限制旧领导与重复投票。任期term是递增的逻辑编号,候选者开始选举先加一并投自己;每个节点同一任期最多投给一个候选者,候选者取得整个配置的多数票才成为领导。三节点多数是2,不能按“现在能联系到的节点”重新缩分母。看到更高任期时更新本地term、清除旧任期投票并退为跟随者;旧领导未获知新任期时可以自认为仍是领导,却不能凭本地身份安全提交。

投票还检查候选日志是否至少一样新:先比较最后条目的任期,任期相同再比较最后索引。日志长但最后任期旧,不一定比短日志新。term、votedFor和日志在真实协议中必须在相应回复前可靠持久化,崩溃后忘记投票会破坏同任期最多一票。这里的完整文件仅在离线内存中推演已指定的消息顺序,不实现持久存储、随机选举超时、RPC、重启、成员变更或快照。

日志匹配与提交安全 ​

日志匹配与提交安全不能简化成“副本数够就成功”。AppendEntries带前一索引与任期,接收端前缀不匹配就拒绝;匹配后才比较后续条目,遇到不同任期的冲突才截断未提交后缀并追加。合法协议历史中,同一索引同一任期意味着相同条目和此前相同前缀;任意拼出来的初始日志不能拿来反驳这个归纳不变量。领导记录各节点确认匹配的matchIndex,而不是把投票当作日志复制确认。

领导只能对本任期条目按多数确认直接推进commitIndex;旧任期条目即使此刻在多数节点上,也不能仅据数量直接宣布提交。提交一个本任期条目会连带提交其前缀。多数交集、候选日志新旧限制及本任期提交条件共同维护后继领导包含已提交条目的安全性质;副本按索引顺序应用已提交命令,不能看到一个未提交条目就先执行。原论文图8展示旧条目暂时在多数上仍可被未来合法领导覆盖的历史,缺少当前任期条件会误判。依据Ongaro与Ousterhout原论文图2、§5.2–5.4,核对日期2026-10-17;本例是核心规则的顺序推演器,不声称完整Raft实现或形式化证明。

因果并发与分区读的不同问题 ​

向量不可比较说明没有已知因果先行,不能据此自动选择业务胜者。分区期间,节点无法确认另一边是否已接受更新;若要保持线性一致,某些请求就不能在失去必要通信后继续成功。以下为两节点寄存器的简化反例,重点是读写历史而非副本数量。

查看图表代码

从日志接收到提交的门槛 ​

接收日志、复制确认和状态机应用是三个时刻。图示为本课领导推进提交的核心检查:未获多数不能提交;仅旧任期条目达到多数也不能据此直接推进。实际协议还依赖任期、持久化和选举限制共同成立,不能从这张局部流程图推出完整正确性。

查看图表代码

来源与适用边界 ​

时钟与事件溯源的公共参考见前文来源;Raft 的日志规则依据见日志匹配与提交安全。 CAP 的原文与同步假设见前文公共参考。

冲突处理、写入超时与一致性边界 ​

最终一致还需什么 ​

最终一致还需什么应明确回答:冲突规则与传播假设:停止新更新且消息最终传达后,各副本才有机会收敛。两个客户端同时修改姓名时,最后写入覆盖可能丢弃一个意图;集合合并适合某些数据,但不能把余额简单取最大当通用方案。

超时后的写入状态 ​

超时后的写入状态是未知,可能已提交但确认丢失。恢复需同一幂等键查询或重放,而不是凭客户端超时回滚已被其他进程看到的结果。补偿是新的业务操作,也会失败;它不把已经发生的外部事实从历史中抹除。

一致性原文阅读边界 ​

一致性原文阅读边界区分1978逻辑时钟与2002CAP论证,以及作者2012回顾对同步假设的讨论。中文官方事件溯源资料用于比较事件与状态,不作为CAP证明。此课不实现共识算法,不把向量时钟算例包装成分布式数据库。

确认丢失后的重试不能换请求身份 ​

客户端只看见超时,无法判断服务端是否提交。若生成新键重发,服务端会把它当成另一项操作;同一键的结果查询或幂等重放才保留原请求身份。幂等记录与业务变更必须具有一致的提交边界,否则仍可能出现已扣款却查不到结果。

查看图表代码

来源与适用边界 ​

时钟与事件溯源的公共参考见前文来源;Raft 的日志规则依据见日志匹配与提交安全。

继续阅读