第4章 Paxos算法精解:Basic Paxos、Multi-Paxos、角色与阶段

在零信任网络里,每个节点都可能被攻破,但整个系统还得对外输出一致的结果。这靠什么?靠共识算法。Paxos是其中教科书级的存在。说实话,我早年刚接触Paxos时,觉得它就是一套晦涩的数学证明。后来调了几年分布式系统,才真正摸到它的筋骨。

先绕个弯子:Paxos并不直接给你一个“最终一致性数据库”,它只解决一件事——如何在多个不可靠的节点间,对某一个值达成确定性共识。零信任场景下,这个“值”可以是某个主机的信任评分,也可以是一条访问控制规则。

4.1 Basic Paxos 经典两阶段

Basic Paxos定义了三个角色:Proposer(提议者)、Acceptor(接受者)、Learner(学习者)。它们之间的交互分两个阶段。

  • 阶段一(Prepare):Proposer生成一个全局递增的提案编号N,向所有Acceptor发送Prepare(N)。Acceptor承诺:如果没接受过编号≥N的提案,就响应自己的已接受记录(如果有);否则忽略。
  • 阶段二(Accept):Proposer收到多数派响应后,从响应中选取已接受提案的值,或自己选一个新值。然后向所有Acceptor发送Accept(N, V)。Acceptor检查编号是否仍然最大,是则接受。

关键约束:Acceptor一旦承诺更高的编号N+1,就不能再接受编号N的提案。这就是Paxos正确的核心——安全性(Safety)保证只有一个值被选定。

我做第一个分布式KV系统时就是按这个两阶段手写的。结果遇到一个坑:Proposer不断自增编号,导致活锁,谁都没法提交成功。后来加了一个超时随机回退,才跑通。嗯,这里要特别提醒——Basic Paxos不保证必然终止,实际工程必须加冲突规避机制。

4.2 Multi-Paxos 性能优化

Basic Paxos每决定一个值就要两轮RTT,成本太高。Multi-Paxos的思路是:选一个Leader,让Leader在其任期内跳过Prepare阶段。

对比项 Basic Paxos Multi-Paxos(Leader模式)
阶段数 Prepare + Accept(2 RTT) 仅Accept(1 RTT,Leader稳定后)
Leader角色 无固定Leader,多Proposer竞争 选举一个Leader,其他为Follower
提案编号 每次提案需新编号 Leader使用唯一递增序列号
典型应用 元数据选主 日志复制、状态机同步

说白了,Multi-Paxos把“选主”和“复制”分开。Leader先通过一轮Basic Paxos或其它方式确立自己的身份。之后所有提案都由Leader发出,Acceptor只需要对序列号做单调递增检查。

曾经踩过的坑:我在一个6节点集群里部署Multi-Paxos,网络出现分区时,两个分区各自选出Leader,导致“双主”同时写日志。Raft用超时随机化解决了这个问题,而Multi-Paxos原并没严格规定Leader选举时序。所以你实现Multi-Paxos时,必须自己设计一套租约或Epoch机制来防止脑裂。

4.3 角色与阶段的本质

不管你用Basic还是Multi,角色本质上是一组逻辑职责。同一个节点可以兼任多个角色。零信任网络下,每个角色做的事都要经过最少权限验证。比如Acceptor不能主动发起提案,Learner只读不能写。

我建议你在设计协议时,把角色和网络身份绑定成独立的微服务单元。一个服务如果只当Learner,那它的网络权限只开放读端口,写端口全关掉。这样即使被攻破,攻击者也做不了破坏。

4.4 核心流程可视化

下面这张图展示Basic Paxos两阶段握手,以及Multi-Paxos如何通过Leader跳过Prepare简化流程。我把它画成流程图,方便你对照代码推导。

Paxos两阶段 vs Multi-Paxos Leader模式 Basic Paxos(经典两阶段) Proposer Acceptor 1 Acceptor 2 Acceptor 3 Prepare(N) Promise / 已接受值 Multi-Paxos(Leader跳过Prepare) Leader Aceptor Aceptor Aceptor Accept(N, V) 直接 Accepted (多数回复即选定) ⚠ 注意:Multi-Paxos通过“选主”省去Phase1的Prepare交互。 但选主本身仍需一轮Paxos或租约协议,不能直接硬编码。 角色说明:Proposer(发提案)→ Acceptor(表决)→ Learner(学习结果) 零信任建议:不同角色分离网络权限;Learner只开放读端口。 零信任一致性校验 第4章 / 30

4.5 工程落地与零信任适配

你可能会问:“Paxos是几十年前的老东西,跟零信任有什么直接关系?”关系大了。零信任网络里,每次访问决策都需要跨节点一致确认。例如一个用户要访问机密文件,策略决策点(PDP)需要从多个策略引擎获取评分,然后对评分做共识。这正好用Paxos来保证每个决策全局唯一。

我的工程建议:

  • 不要自己手写Paxos,用成熟库(比如etcd的Raft实现)。但理解Basic Paxos有助于调试脑裂和活锁。
  • 在零信任场景下,Acceptor数量建议至少5个,容忍2个节点被攻破仍然正确。
  • Learner可分布在所有控制面节点上,它们只读,这样攻击者即使控制一个Learner也改不了已经提交的决策。

4.6 避坑三连(我亲身经历的)

  1. 编号绕回:曾经有一个系统把提案编号设为uint32,结果高并发下编号溢出绕回,Acceptor把新提案当成旧提案忽略——整个集群锁死。建议用uint64+单调递增,或干脆用时间戳+节点ID。
  2. 日志截断与快照:Multi-Paxos如果不做定期snapshot,Acceptor的内存/磁盘会被日志撑爆。我当时没预估好,线上节点OOM了三次才老实加上快照机制。
  3. 网络分区下的脏读:零信任环境常有多路径网络,某个Acceptor可能延迟很久才收到Accept消息。如果你在Learner端不按“多数派提交”来读取,就会读到未最终确认的值。记住:只有被多数Acceptor接受的值才是最终值。

好了,Basic Paxos和Multi-Paxos的骨架就这些。你如果要去实现一个零信任下的信任评分共识模块,完全可以复用这里的思路:选一个Leader,让Leader批量提交评分到Acceptor,Learner从Acceptor拿到多数确认后广播给执行层。注意编号不回绕,超时加随机化,做好snapshot——这几点做到,基本不会翻车。