故事

战国末年,秦将王翦率大军攻楚。楚地广袤,楚将项燕以主力驻郢城南面的云梦泽中,凭借湖沼之险据守。

王翦之策,是分兵两路夹击——自己率北路主力自西北而来,副将蒙武率南路偏师自东南而来。两军须同日同时发动攻击,方能让项燕腹背受敌;若两军其中一路先发而另一路未至,则先发之军势孤力单,反为项燕各个击破。

两军相距百里,中间隔着云梦泽与项燕的主力。传令只能靠斥候——快马加鞭从一路驰向另一路,但须绕过项燕的岗哨,穿越沼泽荒野。斥候常被楚军伏击、被野兽所食、被泥泽所陷,十有三四中途丧命。

王翦召来亲信校尉公子无恤,授以密令:"你带一封帛书去蒙武那里,约定五日后辰时三刻同时发兵。若帛书送到,蒙武自会依期而动。"

无恤领命,欲启程。却忽然皱眉问:"将军,可是——蒙武将军收到帛书之后,他如何让您知道他收到了?若他默默准备,您这边并不知他是否收到,岂不是照常发兵,而他那边万一没收到,便是您孤军深入?"

王翦一怔。他思忖片刻,说:"不错,须让蒙武回信。他收到我的帛书,便立即遣一斥候回报:'已收到,届时必至。'如此我便心中有数。"

无恤依计而行,辗转五日,九死一生,终于将帛书送到蒙武手中。蒙武阅罢大喜,即刻召来自己的亲信田班,命他送回音。

田班临行前,却也皱眉问:"将军,王翦将军派人送帛书来,若他见我们的回音,便知我们已收到,此事便成。可——我们的回音若中途失落,王翦将军便不知我们收到与否,他便会犹豫是否依期发兵。我们依期而动,而他犹豫未动,岂不又是我们孤军?"

蒙武一滞。他沉思良久,说:"你说得有理。那便请王翦将军再回一信——他收到我们的回音之后,再发一信告诉我们:'已收到你们的回音,届时我必依期。'如此我们便知他心中确信,必会依期而动。"

田班点头,出发了。又是五日艰险,田班将回音送到了王翦手中。王翦读罢,正欲依蒙武之请再发一信,忽然停笔。

他召来无恤:"无恤,你说——我现在发一封信给蒙武,告诉他'我已收到你们的回音,届时必依期'。这信送到蒙武那里,蒙武便心安。可——"

"可这信若送不到,蒙武便不知我是否收到了他的回音。他便会怀疑我是否仍会依期而动。他便会犹豫。他一犹豫,我们那边若依期发兵,我便又成了孤军。"

无恤苦笑:"是这般道理。故而将军须再请蒙武将军回一信,说'已收到您的确认,我确信您会依期'。"

王翦冷笑:"那这'确信的确认'送达之后呢?蒙武又要担心我是否收到他的'确信的确认',他便又要我再回一信……如此下去,何时是个尽头?"

无恤沉默良久。他终于轻声道:"将军,这般推下去,永远没有尽头。无论我们互送多少封信、多少次回音、多少层确认——最后那封信,总是悬在半空,没有回音。而发出最后那封信的一方,永远不知道对方是否收到了它。"

帐中烛火摇曳。王翦久久不语,望着面前的沙盘。

夜深了。王翦终于开口:"无恤,你说——这般来回确认,是要求一件天上没有的事:两军之间,永远无法真正'同时确信'对方也确信。我们追求的那种'万无一失的默契',是不存在的。"

"那将军……"

王翦起身,走到帐外,望着漆黑的夜空,缓缓道:

"那便只能——两军各自依照原约,不再等候进一步的确认。 五日前我已遣无恤送去帛书,约定同日同时发兵。无论蒙武是否回音、回音是否送达、我是否再回音、再回音是否送达——都不再等待。到了那一日那一刻,我便发兵。他那边若也发兵,则夹击成;若他那边未发兵,则我便依计退兵,另图后策。"

无恤惊道:"将军,这岂不是赌博?"

王翦摇头:"无恤,天下之事,并非事事可以万全。两军百里相望,中隔敌境,斥候九死一生——在这样的情境下,我们能做的,只是尽量让双方知晓约定;而这'知晓'到底有多牢固,终有一层无法被完全填实。"

"若我们一定要等到'完全确信对方也完全确信'方才行动,那便永远不会行动——因为那一天永远不会到来。"

"真正的将领,不是追求那不存在的完美默契,而是——在不完美的约定上,决断何时行动。"

无恤良久方道:"那若蒙武将军那边也作此想,他是否也会依原约发兵?"

王翦苦笑:"我信他会。因为我们早有约定,我们互相了解彼此的性情。但——这'信'并非来自某封回音的确认,而是来自我们多年来并肩征战积累的默契与信任。"

"信使穿越荒野,能传的只是文字。而支撑两军同心的,从来不是文字的准确送达,而是两位将领之间预先建立的那种'不必细说也知对方会如何'的信念。"

无恤若有所悟。他又问:"可是将军,若将领之间并无此等默契呢?若那是两位素不相识的将军呢?"

王翦久久不答。良久他轻声道:

"那便永远无法真正协同作战。因为两军之间若无超出文字之外的信任,便只能依赖文字的确认;而文字的确认有一条无形的天花板——无论送多少封、回多少次,最后那封总是悬在半空。"

"世间有些协同,文字可以达成;有些协同,文字永远不够。分清这两种协同,是为将之道。"

概念解析

这则寓言讲的是分布式系统理论中最著名、也最具哲学冲击力的不可能性结果之一——两军问题(Two Generals' Problem),又称协调攻击问题(Coordinated Attack Problem)。这一问题最早由 Akkoyunlu、Ekanadham、Huber 于 1975 年形式化提出,后被 Jim Gray 于 1978 年推广。

问题: 两个进程(两位将军)希望在不可靠信道上达成一致——双方必须要么都执行某一动作(同时发起攻击),要么都不执行(都不发起攻击)。若只有一方执行,则结果是灾难性的(孤军深入)。他们只能通过消息传递通信,而消息可能丢失。

问题问:是否存在任何协议,能让两位将军在有限次消息交换后,都确信对方会执行行动?

答案:不存在。 这是一个可证明的不可能性结果。

证明概要(反证法):

假设存在这样的协议 P,它只需有限次消息交换便能让双方达成确信。考虑 P 中最后被成功发送的那条消息 M:

  • 发送方 S 发出 M 之后,若 S 在发出 M 之前已经"确信",那么 M 显然是多余的。
  • 若 S 是在发出 M 之后才"确信",则 S 的确信依赖于 M 被接收方 R 所收到——但 S 并不知道 M 是否真的送达(M 可能丢失)。
  • 那么必须 R 再回一条消息 M' 来确认收到 M。但这样 M 就不是最后一条消息了,与假设矛盾。

归纳下去,无论协议包含多少消息,总会有一条"最后的消息",而发送这条消息的一方永远无法知道对方是否收到了它。因此,没有任何协议能够保证双方在有限轮内都达到"确信"状态。

这正对应寓言中王翦最终所悟:"最后那封信,总是悬在半空,没有回音。而发出最后那封信的一方,永远不知道对方是否收到了它。"

关键理解——这不是工程问题,而是逻辑不可能性:

许多初学者读到两军问题,会想:"那就让协议多发几次确认不就行了?"或"用可靠协议(如 TCP)不就解决了吗?"——这些想法都是错的

两军问题的不可能性不是因为我们不够聪明、工具不够好,而是因为这是逻辑上的不可能——类似于"无法用直尺与圆规三等分任意角"这类问题。无论你投入多少工程努力,都无法达到"双方在有限轮后都 100% 确信对方会执行"。

TCP 并不解决两军问题——TCP 只是让连接建立的失败概率足够低以至于实用。TCP 的三次握手依然存在"最后一个 ACK 可能丢失"的问题,但这在工程上被超时、重试、心跳所掩盖。

深层含义——"共同知识"的不可达成:

两军问题与共同知识(Common Knowledge)这一概念密切相关。共同知识的定义是:

  • 第 1 层:A 知道 P。
  • 第 2 层:A 知道 B 知道 P;B 知道 A 知道 P。
  • 第 3 层:A 知道 B 知道 A 知道 P;B 知道 A 知道 B 知道 P。
  • ……
  • 无穷层:以上所有层都成立。

只有当共同知识达到无穷层时,它才成为真正的共同知识。两军问题证明了:在不可靠信道上,真正的共同知识不可达成——无论多少层次的"我知道你知道我知道……"都无法真正闭合。

这是一个深刻的哲学结论。它告诉我们——绝对的协同,在分布式环境中是不可能的。我们日常生活中的许多"协同"(约定、合同、协议),之所以能工作,并非因为我们真正达成了无穷层的共同知识,而是因为我们在有限层的共识基础上,辅以信任惯例惩罚机制来填补无法达成的那部分。

正是寓言最后所揭示的——"支撑两军同心的,从来不是文字的准确送达,而是两位将领之间预先建立的那种'不必细说也知对方会如何'的信念。"

实践上如何处理:

既然完美协同不可能,现实中的分布式系统如何应对?答案是:放弃"完美",追求"足够好"

  • 超时与重试: 无限等待"最后一个 ACK"会死锁;故而设置超时,超时后假定对方已收到并继续行动(或放弃)。
  • 幂等性: 既然无法保证消息恰好送达一次,便让接收方的操作具备幂等性——多次送达等同于一次送达(前文《两位信使》)。
  • 概率性保证: TCP、DTLS 等协议通过多轮确认,让通信失败的概率降至工程可接受的水平(如 10⁻⁹)。这是概率上的几乎共识,而非绝对共识。
  • 三阶段提交(3PC)与 Paxos: 分布式事务协议通过引入更多轮次、超时机制、协调者变更,处理各种故障场景。但它们都无法绕过两军问题的根本限制——它们只是让问题在特定故障模型(如同步网络、仅节点崩溃)下变得可处理。
  • 信任与声誉: 正如寓言所言,当文字的确认达到极限时,协同便要仰赖超越文字的信任——这在实践中对应于合同、法律、商业信誉、长期关系等"系统外的保障"。

与其他不可能性结果的关系:

两军问题是分布式系统中最早的不可能性结果,它为后续一系列更复杂的定理奠定了基础:

  • FLP 不可能性(Fischer-Lynch-Paterson, 1985): 在异步网络中,即使只有一个进程可能崩溃,确定性共识也不可能达成。FLP 比两军问题更强——它考虑的是异步故障模型下的共识,而两军问题考虑的是同步但信道不可靠的协同
  • CAP 定理(Gilbert & Lynch, 2002): 在网络分区下,强一致性与可用性不可兼得。CAP 可视为两军问题的一种特定化体现——分区就相当于"信道完全失效"的极端情况。
  • 拜占庭将军问题(Lamport et al., 1982): 在消息可能被恶意篡改的环境中,达成一致需要至少 3f+1 个节点。拜占庭问题比两军问题更难——不只是消息丢失,还有消息造假。

关键洞察——区分"弱协同"与"强协同":

分布式系统设计中一条重要的原则,正是寓言末尾所点出的:

世间有些协同,文字可以达成;有些协同,文字永远不够。分清这两种协同,是为将之道。

  • 弱协同(最终一致): 双方最终会达成某种一致状态,但不要求在某一瞬间同步。适用于大多数实际场景——邮件系统、消息队列、CRDT 等。这种协同在不可靠信道上是可以达成的。
  • 强协同(原子协同): 双方必须在某一瞬间同步执行某个动作,要么都执行,要么都不执行。这种协同在不可靠信道上理论上不可达成——实际系统只能通过超时、重试、异常回滚等机制逼近之。

现实意义:

两军问题的教训在现代分布式系统中无处不在——

  • 分布式事务的本质困境: 两阶段提交(2PC)之所以被现代分布式系统所回避,正是因为它在面对协调者故障时会陷入"悬而未决"的状态——这是两军问题的直接体现。
  • 微服务架构的设计哲学: 现代微服务倾向于使用Saga 模式(补偿事务)而非严格的分布式事务,正是因为接受了"完美协同不可能"的现实,转而追求"可恢复的最终一致"。
  • 网络协议的设计: TCP 三次握手、TLS 握手、WebRTC 连接建立——所有这些都带有"最后一个 ACK 可能丢失"的阴影,通过超时与重试来实用化地解决。
  • 分布式锁的陷阱: 分布式锁试图实现"谁拥有这把锁,谁才能操作"——但"对方是否真的释放了锁"这一信息也面临两军问题。这是下一篇《旧符新令》将详细讨论的主题。
  • 区块链的最终性(Finality): 比特币永远不能 100% 保证一笔交易"绝对确认"——区块越深,推翻概率越低,但永远不为零。这也是两军问题在去中心化账本上的体现。

哲学启示:

两军问题揭示的,是分布式协作的根本性限制——这种限制不可逾越,不可绕过,不可用任何工程手段彻底消除。

它教给我们的,不是绝望,而是边界感

分布式系统工程师最深的修养,不是以为自己能造出完美协同的系统,而是——看清哪里是不可为之地,并在可为之地尽可能地做到最好。

这一智慧远超技术本身。它在人类一切协作活动中都有回响——婚姻、合同、外交、公司治理、国际协议——任何两个主体之间的协作,都受制于两军问题的阴影。而人类文明之所以能在这种不可能性下运转,正是因为我们用信任、习俗、法律、惩罚、长期关系这些"系统外"的机制,填补了"协议内"无法填补的那一层。

正如王翦所言:

真正的将领,不是追求那不存在的完美默契,而是——在不完美的约定上,决断何时行动。

这恰是所有分布式系统设计者最深的一课。