分布式系统 11:Raft 任期、投票与选举安全
三台服务器 A、B、C 同时竞选。A 得到自己和 C 的票,成为领导者;随后 C 重启,忘掉已经投给 A 的记录,又投给 B。B 加上自己的票,也达到了多数。每次计票都没有算错,集群却在同一轮选出了两个领导者。 问题出在投票承诺没有跨越重启。一次选举能否安全,不只取决于票数,还取决于票属于哪一轮、由谁投出,以及已经回复成功的投票是否还能被遗忘。 第 10 篇 将稳定领导者与多槽日志联系起来。本篇开始构建另一条可累计的实现:先完成 Raft 的选举状态转换,下一篇再加入日志复制与提交。本篇的 Go 核心会继续复用;当前尚不能存储客户端命令,也不提供完整 Raft 服务。 任期把局部观察分开 采用一个固定成员配置,成员身份在实验期间不变。进程可能崩溃恢复,消息可能延迟、丢失、重复或乱序;节点不伪造身份、不发送任意错误内容。多数指完整配置中超过一半的成员,三节点需要两票,五节点需要三票,不能因两台暂时不可达就缩小分母。 每个节点保存自己的 currentTerm,即已经知道的最高任期。任期是逻辑轮次,不是由统一时钟切出的时间段。A 已经进入 term 4,隔离中的 B 仍可能只知道 t...
分布式系统 21:etcd 的读、事务、Watch 与 Lease
Watch 恢复时,保存“刚收到的 revision”还不够。一笔事务在修订 2 同时改了两个键,消费者只应用第一个事件就把续传位置记成 3,重连后会永久漏掉第二个键。服务端已经完整发送,错误发生在消费端的检查点。 分布式系统 20:etcd 的 Raft 与存储路径 前篇区分了 Raft 位置与 KV revision。本篇使用同一官方 etcd 3.7.1,讨论默认读、条件事务、Watch 恢复与 Lease。核心问题是:一次 API 响应究竟证明了什么,客户端需要补上哪些状态管理,才能把产品保证变成正确的业务行为。 默认读与 serializable 读 默认 KV 操作保证严格可串行化,并遵守实时时序。写已经成功完成,随后发起的读不能返回该写之前的状态,除非又发生了合法的后续修改。对于单次读,可以在调用与响应之间选择一个线性化点。与读并发的写可以排在这个点前或后,不能要求返回值包含直到响应最后一刻才完成的所有写入。API guarantees etcd 的默认 Range 先执行 LinearizableReadNotify,再读取 KV;serializable=tr...
Claude Code 源码深度解析:五层架构与核心设计模式
Claude Code 的工程复杂度集中在模型调用之外:工具怎样获得执行权限,长会话怎样压缩,子任务怎样隔离,失败之后怎样恢复。2026 年 3 月暴露的源码快照让这些机制有了可研究的实现样本;随后数月的文档和版本变化,又说明其中哪些抽象保留下来、哪些接口已经改变。 本文核对资料截至 2026 年 9 月 19 日。历史实现以 v2.1.88 的公开研究为边界,当前功能对照官方文档与当天发布的 v2.1.278。五层架构是一种阅读视图,不代表 Anthropic 对外承诺的固定模块划分。 从泄露快照到持续演进的产品 3 月 31 日的 source map 事件暴露了 Claude Code CLI 应用的大量 TypeScript 源码。它提供了客户端运行时的研究材料,不能等同于模型权重、训练系统或全部云端服务的开源。文件数和行数受生成文件、依赖及统计口径影响,分析架构时更有用的是固定版本与调用关系。 社区研究已经从罗列隐藏开关,转向解释执行系统。论文 Dive into Claude Code 于 4 月 14 日提交,7 月 2 日更新 v2;其研究对象仍是 v2.1.8...
分布式系统 10:Multi-Paxos 与复制状态机
单值 Paxos 为一个位置选定一个值。数据库却要不断处理请求:先设置余额,再扣款,再读取结果。即使每个位置都不会选出两个不同命令,副本按不同顺序执行这些位置,仍可能得到不同余额。Multi-Paxos 需要把逐槽共识、领导者恢复和状态机执行连接起来。 上一篇:多数派交叉与单值 Paxos建立了单值 Paxos 的承诺与选值规则。本篇沿用多数派交叉的证明方法,把共识实例扩展成日志槽。MIT 6.5840 的 Paxos 讲义也通过有序日志连接共识与数据库复制;Stanford CS244B 的课程路线提供复制与容错背景,不将其课程日程当作特定 Multi-Paxos 实现的规范。 槽号与轮号是两个维度 日志槽号 slot 表示命令的执行位置;轮号 ballot 表示一次提案权限的竞争。一个领导者可以在同一轮里推进多个槽,一个槽也可能经过多轮恢复。把它们合成一个递增整数,会丢掉“同一槽在不同轮里接受过什么”的信息。 本篇固定三个 acceptor A、B、C,多数派为两个。P 独占轮号 1,Q 独占轮号 2;两个领导者可以在一段时间内都运行。唯一轮号所有者保证同一 (ballot,...
分布式系统 20:etcd 的 Raft 与存储路径
一次删除不存在键的请求,可以让 etcd 的 Raft 提交位置从 7 增长到 8,而 KV revision 仍为 4。这并不矛盾:日志记录需要按序执行的请求,修订记录实际发生的 KV 状态变化。两个计数器回答的问题不同。 分布式系统 19:ZooKeeper 一致性、锁配方与外部 fencing 前篇已把协调服务的资格判断与外部资源写入分开。etcd 的同类分析还要穿过复制日志、状态机应用和本地存储三层。本文固定 etcd 3.7.1,依据官方文档、固定版本源码和真实单成员实验,解释一次写入如何变成可读状态,以及重启为何不能简单重放整份 WAL。 一个请求经过哪些位置 Raft 日志条目具有 index 和 term。index 表示日志位置,term 标识条目产生的任期;本地保存某条日志不等于已经达成提交条件。提交前缀确定哪些条目可以进入状态机,各成员随后按序 apply,成员之间的应用进度可以不同。 KV revision 则属于 MVCC 状态机。一个写事务实际修改了 KV,才产生新的主修订。内部日志项、不修改任何键的删除、租约元数据操作,都可能消耗 Raft 日志位...
分布式系统 09:多数派交叉与单值 Paxos
A、B 已经接受 X,C 尚未收到消息,提议者又失联了。另一个提议者向 B、C 发起 Y,B 能否再接受?只规定“得到多数票即可成功”,两个值都可能拿到两票。禁止每个节点再次投票也不够:第一轮的票分散后,所有节点可能永久停在不同候选值上。 第 08 篇区分了安全性与活性。单值 Paxos 允许不断发起新一轮尝试,同时限制后续提案的取值,使所有获得多数接受的提案携带同一个值。MIT 6.5840 的 Paxos 讲义从多数派和两阶段进入这一问题;本篇以 Lamport 的原论文及课程精确伪代码为依据,推导约束,并用有限消息调度检查违反约束的后果。 MIT Paxos 讲义。 一次共识的模型和三个角色 本篇只有一个共识实例,成员固定为 A、B、C,法定集合 quorum 取任意两个 acceptor。一般多数派大小为 floor(N/2)+1。进程遵守协议,消息可以延迟、重复或丢失,但不被伪造;进程可以崩溃恢复,持久状态须在恢复后保留。这些约束不覆盖拜占庭行为和磁盘状态永久丢失。 proposer 生成提案,acceptor 持有承诺和接受记录,learner 根据接受证据得知结果。...
分布式系统 08:共识问题与安全活性边界
主节点没有按时回复,备节点能否立即接管?第 07 篇的主备与链式复制把这个问题留在了故障时间线上:旧主可能已经停止,也可能仍在接收写入,只是无法与备节点通信。两个节点分别开始服务,数据复制得再快,也不能补回对写入顺序缺失的共同决定。 一次共识先缩小这个问题:固定一组进程,各自提出一个值,最终决定同一个值。日志复制可以连续处理多个这样的决定,但单次共识的边界需要先明确。MIT 6.5840 的 Paxos 讲义从故障与网络延迟难以区分切入;Stanford CS244b 把 FLP 放在开篇阅读。本篇沿着这一课程顺序,讨论决定必须满足什么,以及何种环境允许决定最终发生。MIT 2026 Lecture 4、Stanford 2024课程表。 共识需要同时限制结果与等待 考虑 A、B、C 三个进程,输入分别为 0、1、1。这里采用停止故障模型:进程可以永久停止执行,存活进程遵守算法,不伪造消息。成员集合事先固定;消息不会凭空产生或被篡改。崩溃恢复、动态成员和拜占庭故障需要额外定义。 一次决定是不可撤销的输出。暂存候选值、投票、收到多数回复都不能未经论证就称为决定。采用以下四个目标时,...
分布式系统 07:主备与链式复制
主节点返回写入成功后立刻故障,备节点接管却读不到这次写入。副本没有同时损坏,客户端也没有误读响应;只要成功响应早于复制完成,这条时间线就可能成立。复制协议要规定的,正是哪些事件必须发生在成功之前,以及换主之后哪些结果必须保留。 上一篇:一致性模型与分区边界给出了检查读写历史的标准。本篇把标准落到主备与链式复制的确认点上。课程结构参考 MIT 6.5840 2026 的 Chain Replication 讲义,协议以 OSDI 2004 原论文为依据;PostgreSQL 18.6 只用于核对真实产品的配置语义,配套程序是独立的有限事件模型。 成功、复制与可读是三个事件 设一个寄存器初值为 x=0,客户端提交 Put(x,1)。主节点可以先更新内存、记录日志,再把变化发送给备节点。备节点收到字节、写入本地日志、刷入稳定存储和应用到查询状态,各自需要不同步骤。“已经复制”若不指明其中哪一步,就不足以解释一次故障后的结果。 异步主备允许主节点在备节点达到所需状态之前返回成功。如下时间线中,主节点本地数据甚至可以已经落盘,切换仍会丢失这次已确认写入: 123P: 写入 1 ── 返回 ...
分布式系统 06:一致性模型与分区边界
客户端 A 写入 x=1 并收到成功,客户端 B 随后读到 x=0。这个结果是否错误,取决于存储接口承诺的一致性模型。若接口承诺线性一致,且没有其他写入,它就是反例;若只承诺顺序一致,还要检查客户端之间的程序关系;若只承诺最终收敛,仅凭这一次旧读无法判定违反承诺。 上一篇:时钟与因果偏序用 happens-before 描述事件之间的因果关系。本篇把对象的读写规格加入时间线,区分哪些观察可以由一次合法执行解释。MIT 6.5840 和 Stanford CS244B 都将一致性、复制与容错放在课程主线中;这里先建立检查读写历史的工具,下一篇再比较复制协议如何满足这些约束。 先规定一个读写对象 设一个 KV 对象初始所有键的值都是 0。Put(x,1) 把 x 改为 1,并返回 OK;Get(x) 返回当前 x 的值。单线程执行 Put(x,1); Get(x) 时,读取必须得到 1。这个规则称为顺序规格,独立于对象用内存、磁盘还是多个副本实现。 并发历史记录每个操作的调用和返回事件,也记录客户端身份、参数及返回值。W_A(x,1)[1,4] 表示 A 在事件 1 调用写,在事件 ...
计算机体系结构 06:单周期数据通路
单周期数据通路:一条指令怎样走完五件事 中心问题:如果一条指令必须在一个时钟周期内完成,硬件要给它准备哪些路? 单周期 CPU 把取指、译码、执行、访存、写回放进同一个周期。它不表示真实高性能处理器都这样工作;它的价值在于把“指令语义需要的硬件路径”一次摊开。add 要读两个寄存器、进 ALU、写回寄存器;lw 还要访问数据存储器;sw 写内存但不写寄存器;分支既要比较寄存器,又要决定下一个 PC。 本篇覆盖 add/sub/and/or/addi/andi/ori/lw/sw/beq/bne/blt/bge。证据等级是“手算”和“功能执行”。功能执行指 Python 脚本生成控制表、穷举 ALU 断言并保存静态延迟算式;延迟部分不是周期仿真,也不推进阶段事件。不覆盖 jump、CSR、异常、压缩指令、流水线冒险、多周期控制或真实硬件频率。 依据和边界 RISC-V RV32I 文档给出本篇使用的指令语义:整数寄存器-寄存器指令读 rs1/rs2 并写 rd;立即数逻辑和加法读 rs1 加 sign-extended 12 位立即数;load/store 用 rs1 + offs...


