想象你是班里的团建委员。全班 40 位同学分散在几间教室里,群里消息随时会延迟、丢失甚至乱序。你们每周要定一个目的地:公园还是博物馆?最头疼的是:小 A 拉到了 21 人的票投公园,小 B 也拉到了 21 人投博物馆,两边同时宣布“我们赢了”——到底听谁的?Paxos 就是一套聪明到极致的投票规则。它发现了一条铁律:只要两拨人都拉到超过半数的票,这两拨人必然有交集,至少有一位同学同时收到了两边的消息,能把“已经定下的结果”传过去。利用这个“多数派必相交”的特性,Paxos 保证全网最终只认一个结果,绝不会出现“公园和博物馆同时当选”。更妙的是,它把决策拆成“先小声问一圈旧账、再正式举手表决”两步,让后来提出的新提议只能继承旧结果、不能推翻旧结果。Multi-Paxos 则把这场每周一次的投票改造成流水线:选出一个固定的“班长”连续拍板,效率成倍提升。今天我们就用这场团建投票,把 Paxos 从头到尾讲透。

岗位关联

共识算法是分布式系统的“定盘星”,也是面试中从初级到高级的分水岭。搞懂 Paxos,你才能真正理解 etcd、ZooKeeper、Chubby 为什么可靠,并在系统设计面试中从容应对。这条路很陡,但值得爬。

目录
  1. 可视化演示
  2. 共识问题与多数派思维
  3. 三大角色模型
  4. 编号与承诺机制
  5. 两阶段提交流程
  6. 正确性分析
  7. Multi-Paxos 优化
  8. 工程实践与学习总结
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示Basic Paxos两阶段协议、Multi-Paxos日志复制优化及Quorum法定人数机制,支持模式切换。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Basic Paxos两阶段协议 Prepare阶段Proposer提案获取多数承诺 Accept阶段Proposer发送Accept请求 N > f, Quorum = floor(N/2) + 1 Learner从多数派Acceptor学习最终值

共识问题与多数派思维

把全班 40 位同学想成 40 台服务器,团建群就是网络。你和小 A 同时在群里喊话拉票,可消息会丢、会迟到、会乱序。你俩都以为“拉到一半以上的人就算赢”,但如果两拨人收到的消息不一样,就可能出现两个“过半”同时宣称胜利。直到有人发现:只要两边都超过半数,就必然有一个同学同时收到了两份“投票邀请”,他就是化解冲突的关键。

分布式系统里的情况一模一样:每台服务器都有自己的内存和时钟,无法瞬间看到全局状态。要让所有节点对同一个值达成一致——比如“谁是主节点”“这笔转账是否有效”——只能靠收发消息,而消息恰恰是不可靠的。Paxos 的提出者 Leslie Lamport 把这个难题抽象成“议会立法”:一群议员要投票通过法案,消息会迟到甚至丢失,但最终必须只有一个法案生效。

Paxos 的解决方案立足于一条数学铁律:任何两个“超过半数”的集合必然相交。这就是把“过半民主”升级为“多数派相交”的关键思维——单单比人头不够,还要利用集合必然重叠这一点,让新结果永远无法绕开旧结果。

回到团建投票:你拉到 21 票,小 A 也拉到 21 票,两群人必然有重叠的同学。他的一句话就能让两边知道“公园已经定了”。多数派相交,就是整座 Paxos 大厦的第一块地基。

∀Q1,  Q2∈Q:Q1∩Q2≠∅\forall Q_1,\; Q_2 \in \mathcal{Q}:\quad Q_1 \cap Q_2 \ne \varnothing
任意两个多数派(超过半数的节点集合)必有公共节点。这是共识算法的“抽屉原理”,也是 Paxos 安全性的第一块基石。
  1. \(\mathcal{Q}\) 多数派集合把所有“超过半数节点”的子集收集起来组成一个大集合。Q={ Q⊆V∣∣Q∣>∣V∣/2 }\mathcal{Q} = \{\, Q \subseteq V \mid |Q| > |V|/2\,\}
  2. \(\forall Q_1, Q_2\) 任意两个多数派从集合中任取两拨节点,不关心它们各自具体是谁。Q1,  Q2∈QQ_1,\; Q_2 \in \mathcal{Q}
  3. \(Q_1 \cap Q_2\) 取交集找出同时出现在这两拨节点里的共同成员。Q1∩Q2Q_1 \cap Q_2
  4. \(\ne \varnothing\) 交集非空结论是交集不可能为空——两拨人一定有一个共同的同学。Q1∩Q2≠∅Q_1 \cap Q_2 \neq \varnothing

三大角色模型

一次团建决策需要三种人:出主意的发起人、被咨询并表态的评审团成员、负责写周记的记录员。同一个人可以既是评审又是记录员,全看谁有空。

Paxos 同样定义了三个逻辑角色,它们可以由同一个进程兼职。Proposer(提议者)负责发起提案、推动决策;Acceptor(接受者)负责存储状态、参与表决,是决策的真正“记忆载体”;Learner(学习者)负责把已经选定的结果传播给其他节点。工程上,通常所有节点都同时扮演 Acceptor,其中一个节点兼任 Proposer,形成“班长”。

Acceptor 的职责极其单纯:它只需要记住两笔账——“我承诺过的最大提案编号是多少”和“我真正接受过的(编号,值)是什么”。正是这种极简的状态设计,让 Paxos 的正确性可以被严格证明。

评审团成员其实只记两件事:我见过的最大会议编号是多少、已经圈定的地点叫什么。记好这两笔账,后面的所有承诺规则都会顺理成章。

sa=(rpromised, (racc, vacc))s_a = \bigl( r_{\text{promised}},\ (r_{\text{acc}},\ v_{\text{acc}}) \bigr)
每个接受者只保存一个二元组:已承诺的最大编号 + 已接受的(编号,值)。状态只增不改,编号单调上升。
  1. \(s_a\) 接受者的状态用 \(s_a\) 表示接受者 \(a\) 在当前时刻的全部记忆。sas_a
  2. \(r_{\text{promised}}\) 已承诺编号这个接受者见过并承诺过的最大提案编号,初始为 \(-\infty\) 或空。rpromised, 初始=−∞r_{\text{promised}},\ \text{初始} = -\infty
  3. \((r_{\text{acc}}, v_{\text{acc}})\) 已接受记录它实际接受过的提案编号和对应的值,初始为空。(racc, vacc), 初始=(null, null)(r_{\text{acc}},\ v_{\text{acc}}),\ \text{初始} = (\text{null},\ \text{null})
  4. 只增不改两条记录都只会被更大编号覆盖,绝不会回退到更小编号。rpromised≤rpromised′  ∧  racc≤racc′r_{\text{promised}} \le r_{\text{promised}}' \;\wedge\; r_{\text{acc}} \le r_{\text{acc}}'

编号与承诺机制

班级事务太多,你给每个提议都盖一个编号:001、002、003……编号越大代表消息越“新”。你上一秒定下的“公园”,绝不能被一张迟到的、盖着 001 号的旧纸条推翻。这就是编号的意义:给时间排序,让旧消息失去作祟的能力。

Paxos 用全序的提案编号为每一轮决策排序。为了保证编号全局唯一且可比,工程上常用(任期号,节点 ID)拼接成一个整数——任期号是主维度,节点 ID 用来打散并列。编号不需要连续,只需要严格递增。

Promise(承诺)机制是安全性的核心。当接受者收到编号更大的 prepare 请求时,它会承诺两件事:第一,以后任何编号更小的 accept 请求我一律拒绝;第二,我在回复时把自己知道的历史账本如实上报。这个承诺像一道时间屏障,把“旧决定”和“新提案”隔离开。

这位同学说:“我见过的最大编号是 005,任何小于 005 的纸条请别烦我。”旧纸条就无法把已定的结果改掉——承诺机制就是一道时间屏障。

promise(rp)  ⟺  rp>rpromised\text{promise}(r_p) \iff r_p > r_{\text{promised}}
接受者只对“大于我见过的最大编号”的提案给出承诺;一旦承诺,就再也不会接受任何更小编号的提案。
  1. promise\((r_p)\) 承诺事件接受者对编号 \(r_p\) 的 prepare 请求给出的肯定答复。promise(rp)\text{promise}(r_p)
  2. \(\iff\) 当且仅当承诺发生的条件被精确限定,不多也不少。A  ⟺  BA \iff B
  3. \(r_p > r_{\text{promised}}\) 编号严格更大只有当新编号大于已承诺编号时才答应,等于也不行。rp>rpromisedr_p > r_{\text{promised}}
  4. 承诺的效力答应之后,任何编号 \(\le r_p\) 的 accept 都会被拒绝,已选定的值由此得到保护。accept(n,v)⇒n>rpromised\text{accept}(n, v) \Rightarrow n > r_{\text{promised}}

两阶段提交流程

有了编号和承诺,发起人开始正式操作。关键的一步是:他先不急着表决,而是先“翻旧账”。就像你拿到一个新提案,先在群里小声问一句:“之前定过什么没有?”等多数派回复完毕后,你才发正式表决。

这就是 Paxos 著名的两阶段:阶段一 Prepare,向多数派发送 prepare(n) 请求,收集 promise 和它们的历史已接受记录;阶段二 Accept,根据历史确定最终值 v 后,再向多数派发送 accept(n, v),多数派接受即宣告选定。如果阶段一拿不到多数派承诺,就增大编号重试。

两阶段的灵魂是“值绑定规则”:如果在 prepare 回复中发现任何已接受的历史值,提议者必须沿用其中编号最大的那个,不能自由发挥。这一条让新提案只能“继承”旧结果,从根上杜绝了篡改。

先问旧账再表决,让新提议只能“继承”不能“篡改”。班级记录员把结果写进周记,所有人都不再为同一个地点反复争吵。

vp={vhif (nh,vh) 是回复中编号最大的已接受记录vnewif 不存在任何已接受记录v_p = \begin{cases} v_h & \text{if } (n_h, v_h) \text{ 是回复中编号最大的已接受记录}\\ v_{\text{new}} & \text{if 不存在任何已接受记录} \end{cases}
提议者最终提交的值不是自己随便选的:只要多数派中存在历史决定,就必须沿用编号最大的那个历史值;只有当历史完全空白时,才能自由提出新值。
  1. \(v_p\) 最终提交值提议者经过两阶段后真正要提交给多数派的值。vpv_p
  2. \(v_h\) 历史值某个接受者回复中携带的、曾经被接受过的值。(nh, vh), nh≤n(n_h,\ v_h),\ n_h \le n
  3. 编号最大从所有历史记录中挑出编号最大的一条,取其值。nh=max⁡{ n′∣(n′,v′)∈promise 回复 }n_h = \max\{\, n' \mid (n', v') \in \text{promise 回复}\,\}
  4. \(v_{\text{new}}\) 自由新值只有当集合为空、没有任何历史记录时,才能选一个全新值。vnew∉历史值集合v_{\text{new}} \notin \text{历史值集合}

正确性分析

团建规则有两条底线:已定下的目的地不许反悔——这是安全性;讨论不能无限期拖下去——这是活性。Paxos 对前者给出了严格证明,对后者却“爱莫能助”。

Paxos 的安全性由不变式保证:一旦某个值被多数派选定,之后任何一轮提案被选择的值都必然与它相同。前面所有机制——编号全序、Promise 承诺、值绑定规则——层层嵌套,最终构成了这个不变式的数学证明。证明思路是归纳法:从第一轮开始,若值 v 被选定,则所有后继轮次在 prepare 阶段都会撞见这个值,并被迫继承它。

就像班里两个爱抢风头的同学轮流提出更大编号的议案,会议可以永远开不完。So 大家干脆选一个班长,让他唯一发言——这正是 Multi-Paxos 的出发点。

\left( \textsc{Chosen}(n, v) \;\wedge\; \textsc{Chosen}(n', v') \;\wedge\; n' > n \right) \Rightarrow v' = v
如果编号 n 的提案选定了值 v,那么任何编号更大的提案选定值 v' 时,v' 必然等于 v。已选定的值永远不可被推翻。
  1. Chosen\((n, v)\) 选定谓词表示编号 n 的提案已经被多数派接受,值 v 胜出。\textsc{Chosen}(n, v)
  2. 编号比较 \(n' > n\)后一轮提案拥有更大的编号,代表它“更新”。n′>nn' > n
  3. 蕴含结论 \(v' = v\)前提同时成立时,后选定的值必须与先前完全一致。⇒v′=v\Rightarrow v' = v
  4. 安全性 vs 活性这条不变式只保证“不会选错”,不保证“一定能选出”。两个提议者轮流增大编号,协议会活锁。∃n1<n2<n3<⋯ , 始终无法选定\exists n_1 < n_2 < n_3 < \cdots,\ \text{始终无法选定}

Multi-Paxos 优化

每周团建都要从“翻旧账”开始,实在太蠢了。于是大家约定:选一个班长,班长上任那天问一圈、拿到所有承诺之后,之后每周直接表决、记录。新班长上任才需要重新翻旧账,平时直接流水线推进。

Multi-Paxos 面对的不再是“一个值”,而是“一串值”:把日志的每个槽位当作一次独立的 Basic Paxos 决策。当 leader 稳定时,多个槽位共享同一轮 prepare——班长上任时的承诺对所有槽位都有效,阶段一被大幅省略,只剩连续不断的 accept 消息,形成流水线。

班长掉线了,全班就要重新选班长;新班长第一件事是先翻开周记本,把已提交的日志补全,再继续往后写。Multi-Paxos 没有发明新算法,它只是把旧规则用在了“一串连续决策”上。

L = [\, v_1,\ v_2,\ v_3,\ \ldots,\ v_i,\ \ldots\, ], \qquad v_i = \textsc{Paxos}(i)
Multi-Paxos 把日志看成槽位序列,每个槽位单独跑一轮 Basic Paxos;稳定 leader 时,一次 Prepare 可服务后续所有槽位。
  1. \(L\) 日志全部历史决策的有序序列,就像班级的周记本。LL
  2. \(v_i\) 槽位值第 \(i\) 个槽位对应的值,即第 \(i\) 周的团建目的地。vi, i=1,2,3,…v_i,\ i = 1,2,3,\ldots
  3. Paxos\((i)\) 单轮共识每个槽位独立执行 Basic Paxos 算法选出自己的值。v_i = \textsc{Paxos}(i)
  4. 共享 Prepare同一 leader 在位时,多个槽位复用同一次 Prepare 得到的承诺。Prepare 次数=O(1) per leader term\text{Prepare 次数} = O(1) \text{ per leader term}

工程实践与学习总结

这套投票规则不是纸上谈兵。Google 的 Chubby 用它提供分布式锁和元数据服务,腾讯的 PaxosStore 用它支撑存储系统的一致性,ZooKeeper 的 ZAB、etcd 的 Raft 也都是这个家族的子孙。可以说,Paxos 的子孙撑起了现代分布式系统的半边天。

Raft 常被称为“把 Multi-Paxos 讲成人话”的算法:它把 Multi-Paxos 中隐晦的领导权、日志连续性、任期投票拆成了清晰易懂的模块,让工程实现有了可遵循的教科书。理解 Paxos,你就拥有了看穿 Raft、ZAB 等一切共识协议的“透视眼”。

真正的工程难点从来不在算法本身:状态必须落盘才能容灾,日志要快照压缩,成员变更要小心处理,乱序和重复消息必须去重。班级章程只有一页纸,但要真的运营好,还需要记录员把每一笔写进账本、团长换届时严格交接。从看懂 Basic Paxos 到写好生产级实现,中间隔着大量细节——这也是你从“知道”走向“掌握”的必经之路。

Raft≈Multi-Paxos+强领导+日志连续性约束\text{Raft} \approx \text{Multi-Paxos} + \text{强领导} + \text{日志连续性约束}
这并非严格的数学等式,而是一个概念等式:Raft 就是 Multi-Paxos 加上“强领导 + 日志顺序严格连续”这两个工程简化。
  1. Raft 算法一个面向工程可实现性的共识算法。Raft\text{Raft}
  2. Multi-Paxos 内核Raft 复用了“选班长 + 日志槽位”的核心结构。Multi-Paxos\text{Multi-Paxos}
  3. 强领导日志只能由 leader 追加,交给 leader 判定提交,杜绝乱序。强领导=唯一写入口\text{强领导} = \text{唯一写入口}
  4. 日志连续性约束要求日志索引严格连续、不空洞,从而简化了选举后的对齐。indexnew=indexprev+1\text{index}_{\text{new}} = \text{index}_{\text{prev}} + 1

AI 应用场景

分布式训练参数多副本同步

阶段:模型训练

解决的问题:大模型训练中,参数服务器的多副本需要保持同一份权重。传统主从异步复制在网络分区时可能产生“双主”,两个机房各训各的,模型参数分叉导致训练发散。用类 Paxos 共识决定哪个副本是权威,多数派一致才能切换,从根上消除脑裂。

具体案例:一家公司用 3 副本参数服务器训练百亿参数模型。某机房网络故障后,旧主节点失联;共识协议自动选出新主,且只有获得多数派确认的新主才接受写入。恢复后旧主重新加入,发现自己已被“更小编号”的决策淘汰,自动同步最新权重,训练无损继续。

模型版本发布的全局一致性

阶段:模型部署上线

解决的问题:推荐系统每天多次热更新模型。如果一部分节点已经切到新版本、另一部分还在跑旧版本,同一用户的两次请求会得到互相矛盾的推荐结果。用共识协议让全集群对“当前生效的模型 ID”达成一致,发布和回滚都像一次原子操作。

具体案例:某广告推荐团队用 5 节点配置中心存储“当前模型版本号”。发布新模型时,版本号作为“值”提交给共识集群;只有多数节点确认后,全网才感知新版本。回滚同理——回滚也是一个新提案,它会继承“已被选定的值”的约束,确保不会出现版本跳跃混乱。

特征存储主备自动切换

阶段:数据管道与特征服务

解决的问题:实时特征服务跨机房部署,主节点一旦宕机必须秒级切换。传统心跳检测在分区时可能误判,出现两个主节点同时写特征库。Paxos 保证分区后只有多数派一侧能继续选主,写入永不分裂。

具体案例:一家金融风控公司把特征库部署在 3 个可用区,用类似 Paxos 的协议做选主。一次光缆被挖断导致一个可用区失联,剩余两个可用区仍构成多数派,自动选出新主继续服务;孤立区的旧主发现无法获得多数派支持,主动降级为只读,避免脏写。

Python 演示

python63 行
# -*- coding: utf-8 -*-"""Basic Paxos 最小可运行模拟:3 个接受者 + 2 个提议者"""import sys  class Acceptor(object):    def __init__(self, node_id):        self.node_id = node_id        self.promised = -1          # 承诺过的最大编号        self.accepted = (-1, None)  # 已接受的 (编号, 值)     def prepare(self, n):        if n > self.promised:            self.promised = n            return ("promise", self.accepted)        return ("reject", self.promised)     def accept(self, n, v):        if n >= self.promised:            self.promised = n            self.accepted = (n, v)            return ("accepted", self.node_id)        return ("reject", self.promised)  class Proposer(object):    def __init__(self, acceptors, start_round=0):        self.acceptors = acceptors        self.round = start_round     def propose(self, v):        self.round += 1        n = self.round        # 阶段一: prepare, 收集多数派承诺        promises = []        for a in self.acceptors:            resp, acc = a.prepare(n)            if resp == "promise":                promises.append(acc)        if len(promises) < len(self.acceptors) // 2 + 1:            return None        # 若有历史值, 必须沿用最大编号的那个        latest = max([p for p in promises if p[1] is not None],                     default=(-1, None))        value = latest[1] if latest[1] is not None else v        # 阶段二: accept 提交给多数派        for a in self.acceptors:            a.accept(n, value)        return value  def main():    acceptors = [Acceptor(1), Acceptor(2), Acceptor(3)]    p1 = Proposer(acceptors)    print("第一轮提议公园 -> 选定:", p1.propose("公园"))    p2 = Proposer(acceptors, start_round=10)    print("第二轮想提博物馆 -> 实际:", p2.propose("博物馆"))    print("所有接受者状态:", [(a.node_id, a.accepted) for a in acceptors])    return 0  if __name__ == "__main__":    sys.exit(main())
目的:用 30 行核心逻辑模拟 Basic Paxos 的两阶段提交,并展示“新提案只能继承已选定的值”这一关键性质。
  1. self.promised = -1接受者的承诺编号初始化为 -1,表示“从没见过任何提案”。
  2. def prepare(self, n)只有收到更大编号时才更新承诺并上报历史账本。
  3. if n > self.promised:这就是 Promise 规则:编号严格更小的一律拒之门外。
  4. if len(promises) < len(self.acceptors) // 2 + 1:凑不齐多数派就放弃本轮,等待重试。
  5. value = latest[1] if latest[1] is not None else v值继承规则的核心:有历史值就沿用。
  6. for a in self.acceptors: a.accept(n, value)阶段二把确定好的值正式提交给所有接受者。
  7. start_round=10第二个提议者用更大的编号抢权,却无法改变已被选定的“公园”。

常见误区

误区多数派不就是超过一半吗?只要每次投票拉到一半以上的人就行,这两个“一半”之间可能完全没有关系。

正解两个超过半数的集合必然相交——这是最简单的抽屉原理。正因为任意两个多数派必有公共节点,共识才不会出现两个同时成立的结果。多数派的本质不是“人数多”,而是“任意两拨必相交”。

为何常见:日常投票的直觉是“比谁人多”,很少有人会从集合交叠的角度去想问题,而这恰恰是 Paxos 安全性的根。

误区阶段一就像是先争取支持者,看看谁愿意投我,然后阶段二让这些人正式投票,谁能拉到多数谁就赢。

正解Prepare 的真实目的是“翻旧账”:查明此前是否已有被选定的值,并让接受者做出承诺。若有历史值,提议者必须沿用,不能自由选新值。拉票只是表象,防止旧结果被篡改才是本质。

为何常见:两阶段看起来很像“预热 + 投票”的拉票流程,人们自然把 prepare 当成私下拉票,忽略了它携带历史信息、锁定承诺的核心义务。

误区只要所有节点都按协议办事,Paxos 就一定能选出值,这是算法最基本的承诺。

正解Paxos 严格保证的只有安全性——已选定的值不被推翻。活性需要额外条件:两个提议者轮流用更大编号抢占,就会活锁,理论上可能永远选不出来。工程上正是靠 Multi-Paxos 选举 leader 才打破僵局。

为何常见:教材几乎都强调“达成一致”的目标,读者很容易把目标的期望当成算法实际证明的性质。

误区Basic Paxos 解决单个值,Multi-Paxos 是另一套全新的共识算法,两者关系不大。

正解Multi-Paxos 就是把 Basic Paxos 反复应用到日志的每个槽位上,本质还是同一个协议。差异只在工程优化:当 leader 稳定时,多个槽位共享同一轮 prepare,跳过了重复的阶段一。

为何常见:名字不同加上论文晦涩,读者以为发明了第二套机制;其实区别只在“会话复用”这个工程层面的优化。

面试题

Q1. Paxos 中一个值被“选定”需要满足什么条件?

单选题 · easy

  • A.所有节点都必须接受该值
  • B.超过半数的接受者接受该值← 正确答案
  • C.提议者个人单方面决定
  • D.全体学习者一致点头认可

答案:B。Paxos 只需要多数派(超过一半)接受就算选定。选“所有节点”是多数派思维的常见误解,多数派相交才是安全性的来源,而非全员一致。

Q2. 接受者在收到更大的提案编号后,会做出什么行为?

单选题 · easy

  • A.拒绝所有更小编号的提议
  • B.承诺不再接受更小编号的提议← 正确答案
  • C.立即拒绝所有新来的提议
  • D.向提议者发送拒绝补偿请求

答案:B。接受者承诺“忽略更小编号”,但不会拒绝更大的。这就像同学说“小于 005 的纸条别烦我”,而不是“所有纸条都别烦我”。B 准确描述了 Promise 的语义。

Q3. Prepare 阶段真正的目的是什么?

单选题 · mid

  • A.抢先获得多数派的投票支持权
  • B.查明是否有已选定或即将选定的值← 正确答案
  • C.通知所有节点重启并清理状态
  • D.测试各节点之间的网络延迟情况

答案:B。Prepare 是“翻旧账”,核心是发现历史已接受的值(即将选定的值),并要求多数派承诺不再接受更小编号。拉票只是表象,携带历史信息才是本质。

Q4. 某接受者已对编号 5 给出 Promise,此时收到编号 3 的 accept 请求,它应当?

单选题 · mid

  • A.继续接受该编号的新值
  • B.拒绝该编号并遵守原有承诺← 正确答案
  • C.接受但记录一个异常告警
  • D.退回编号再同提议者协商

答案:B。承诺一旦做出,接受者必须拒绝所有更小编号的 accept。这是 Paxos 防止旧提案推翻新决定的时间屏障,违反它就破坏了安全性。

Q5. Multi-Paxos 相对 Basic Paxos 的核心优化是什么?

单选题 · mid

  • A.减少参与共识的节点数量
  • B.选举固定领导并省略重复准备← 正确答案
  • C.引入更强的拜占庭容错能力
  • D.彻底取消接受者的投票动作

答案:B。Multi-Paxos 选出稳定 leader 后,多个日志槽位共享同一次 Prepare,省去为每个值重复跑阶段一的开销。节点数量与容错模型并未改变。

Q6. 某接受者已接受值为 W 的提案,此时收到编号更大但携带不同值 V 的 accept 请求,正确行为是?

单选题 · extreme

  • A.接受新编号并更新自己的状态← 正确答案
  • B.拒绝新编号以保护历史结果
  • C.只记录但不通知任何学习者
  • D.把决策转发给更高层管理者

答案:A。接受者只检查编号是否不小于已承诺编号,不校验值是否与历史一致。携带不同值说明提议者违反协议假设,但接受者按规则应接受新编号。这道题考察的是“接受者的职责边界”。

Q7. Paxos 算法本身严格保证以下哪种性质?

单选题 · hard

  • A.只严格保证安全性这个性质← 正确答案
  • B.同时保证安全与活性两个性质
  • C.保证协议在最坏情况下的实时性
  • D.保证所有节点最终同时知晓结果

答案:A。Paxos 证明的是安全性(已选定的值不被推翻)。活性只有在额外条件(如选举 leader 消除竞争)下才能获得,两个 proposer 竞争编号可能导致活锁。

Q8. 关于多数派(quorum)相交特性的正确说法是?

多选题 · mid

  • A.任意两个多数派必然拥有公共节点← 正确答案
  • B.一个节点可以同时属于多个多数派← 正确答案
  • C.两个多数派完全不相交也是允许的
  • D.多数派大小等于总节点数的一半

答案:AB。超过半数的两个集合必相交(A 对);一个节点当然可以出现在多个不同多数派中(B 对)。C 违背抽屉原理,D 错在多数派必须严格大于一半而不是等于一半。

Q9. 在 Multi-Paxos 中,稳定 leader 的作用包括?

多选题 · hard

  • A.连续提交提案简化两阶段流程← 正确答案
  • B.维护日志槽位的全局顺序← 正确答案
  • C.彻底消除集群中的所有故障
  • D.替代接受者直接完成值选定

答案:AB。leader 让多个槽位共享 Prepare 并维护日志顺序(A、B)。它不能消除故障,也不能绕过接受者直接选定值——决策仍然需要多数派接受。

Q10. 值被多数派接受并选定后,负责把结果传播给其余节点的是谁?

单选题 · easy

  • A.Proposer 提议者的角色
  • B.Acceptor 接受者的角色
  • C.Learner 学习者的角色← 正确答案
  • D.Client 客户端的角色

答案:C。Learner 的职责就是“学习并传播已选定的结果”,让没有参与投票的节点也能知道最终决定。角色分工是 Paxos 模型的基本知识点。