故事
万历年间,南京刑部有一枚铜印,掌印郎中每日卯时亲启印匣,用印后钤盖"某年某月某日刑部之印"——这行字叫印戳,既是凭证,也是次序。刑部文移万千,哪件先批、哪件后准,全看这枚印当时落在谁手里。
天启五年,掌印郎中暴病身亡,印匣钥匙随他一起入了殓。按规矩,印不可离部,须臾不可无主;但钥匙只有一把,郎中猝死,谁来开匣?
刑部侍郎想了个法子。他把郎中生前常用的三名书吏叫到堂上,说:"印还是那一枚,但今后不用钥匙了。你们三人各持一枚副印,形制一样,只是边角多錾一道齿纹。凡有文书,三人先各自在私簿上记下'今日第几号、所为何事',然后比对——三人簿上同一条目,才能钤印。若有人簿子不同,以多数为准;若三人各写各的,今日便无印可用,文书积压,明日再议。"
这法子有个好处:郎中在不在,印都能用。只要三人中有两人在场,印就能流转。但也有个麻烦:三人若分散在各房办公,谁来发起"今日第几号"的计数?若甲写"第三件"、乙写"第三件"、丙写"第四件",多数虽是"第三件",可丙的簿子从此岔开,以后再也对不上。
侍郎又加了一条:每逢换班,三人须互相抄录对方簿子末尾十行,确认"我看到你的印戳到此为止"。这叫对戳——不是对文书内容,是对彼此见过的历史。抄录之后,三人簿子的"水印"便对齐了,哪怕中间有人漏记一行,也能从邻人的簿子上补回来。
书吏们私下管这叫"旧印"——印还是那枚老铜印,只是用法变了,从"一人独掌"变成"三人共戳",从"钥匙开门"变成"簿子对账"。
—
这枚"旧印"运转了七年,直到崇祯改元。后来的人只记得刑部文书从不断档,却少有人追问:郎中死后那枚真印其实再没开过匣,三年之后打开,铜绿已经蚀穿了印钮。
—
一九八八年,MIT的Barbara Liskov和她的学生Brian Oki在论文里重述了同一套机制。他们面对的当然不是铜印,而是分布式系统里最常见的主从复制:一个主节点处理所有写入,若干从节点同步复制。问题是——主节点崩溃怎么办?谁来接替?接替者怎么知道主节点崩溃前最后一条写的是什么?
他们的答案叫Viewstamped Replication,直译是"视图戳记复制"。核心设计分三层:
视图(View)——系统的配置纪元。每个视图编号对应一个确定的主节点和一组从节点。视图变更好比刑部换班:旧主卸任,新主登基,但交接必须有一套仪式保证不丢文书。
戳记(Stamp)——每条写入携带的序号和视图编号。客户端请求写入时,主节点给它打戳:「视图7,序号153」。从节点按戳排序,不是按到达先后——戳才是权威。
对戳(Checkpoint)——定期固化状态。从节点不是无限追日志,而是每隔一段就做一个快照,然后互相确认"我追到这个戳了"。这对应书吏们抄录彼此簿子末尾十行的仪式。
VR的关键创新在于把共识问题嵌入主从复制的日常流程,而不是像Paxos那样把"选主"和"定序"拆成两个阶段。在VR里,主节点本身就是视图的一部分;视图变更时,新主从旧主的从节点里产生,而旧主的最后一条戳记由多数从节点共同担保——只要多数存活,戳记就不会丢。
这带来一个微妙的优势:VR在正常路径上比Paxos更快。Paxos的Prepare-Promise-Accept三阶段是为最坏情况设计的,即使网络良好也要走完全程。VR假设主节点大部分时间健在,写入只需一阶段广播+从节点确认;只有主节点失效时才触发视图变更的完整协议。用Liskov的话说,这是"优化常见情形,不牺牲安全"。
但VR的代价是主节点是单点瓶颈,所有写入必须经过它;Paxos的多主变体(Multi-Paxos)后来允许不同主节点并发处理不冲突的写入。VR的原论文也没有详细处理网络分区——如果旧主其实没死,只是网络断了,新主登基后可能出现"双主",两人的戳记各自编号,再也对不上。
二〇一二年,Liskov团队发表了VR Revisited,把三十年的工程教训补了回去:显式处理分区、引入leader lease防止脑裂、用quorum交集保证视图变更安全。旧印重新錾了齿纹,又能用了。
—
VR和Paxos的关系,常被说成"殊途同归"——两者都依赖多数派quorum,都用两阶段提交保证安全,都满足FLP不可能性前提下的条件共识。但路径不同:Paxos从"一组提议者竞争定序"出发,VR从"一个主节点带一组从节点复制"出发。前者像议会辩论,后者像衙门流转。
现代系统里,Raft([✓#6 传灯人])的算法结构其实更接近VR:强主节点、日志复制、任期(term)对应VR的视图(view)。Diego Ongaro设计Raft时明确说过,VR的"主从+视图"框架比Paxos更易理解和实现。只是VR的论文发表太早,八十年代的分布式系统还太小众,旧印錾好了齿纹,却等了三十年才被人重新从匣里取出来用。
—
崇祯十五年,南京刑部最后一次用旧印发文。三书吏中一人死于流矢,一人逃亡,剩下一人的簿子写到"视图四百七十二、序号无算"——后面是空白。次年清军渡江,这枚铜印和它的副印一起沉进了秦淮河。
但簿子上的戳记还在。后来有人从故纸堆里翻出抄本,仍能按编号还原那一年刑部批过的全部文书:某月某日准斩、某月某日驳回、某月某日悬而未决——戳记比印活得久,这是侍郎当年没料到的事。
分布式系统里,日志就是簿子,戳记就是视图编号。节点会死,网络会断,但多数派共同承认过的戳记,比任何一枚铜印都活得久。
—
概念解析
Viewstamped Replication(VR)是1988年由Brian Oki和Barbara Liskov提出的共识算法,比Lamport的Paxos(1989年投稿,1990年发表)更早,但长期被忽视。VR的设计目标很明确:在主从复制架构中解决故障切换时的共识问题——新主节点如何安全接替旧主,且不丢失已确认的写入。
视图(View)是VR的核心抽象。每个视图编号绑定一个唯一的主节点和一组从节点(replica group)。系统在正常视图中运行时,所有写入由主节点定序并同步到从节点;当主节点疑似失效时,从节点触发视图变更(view change),选举新主。视图编号单调递增,保证任何时刻只有一个"合法"主节点。
戳记(Stamp)即客户端请求的序号+视图编号。主节点接收请求后分配戳记,广播给从节点;从节点按戳记顺序执行,而非按网络到达顺序。这消除了乱序和重复的不确定性。
Checkpoint是VR的日志截断机制。从节点定期固化状态并交换确认,防止日志无限增长。VR Revisited(2012)在此基础上补充了故障检测、网络分区处理和leader lease优化。
与Paxos/Raft的关系。 三者都基于多数派quorum,安全保证等价(都满足线性一致)。Paxos从"多提议者竞争"出发,协议更通用但也更抽象;VR和Raft从"主从复制"出发,假设强主节点,优化常见路径的性能。Raft的term/leader结构直接继承VR的view/primary框架,只是用更工程化的方式重新表述。
工程遗产。 VR的原型实现影响深远:Liskov的后续工作(包括Byzantine容错版本PBFT的前身思路)都延续这一框架。现代系统如ZooKeeper(ZAB协议)、etcd(Raft)、MongoDB复制集,本质都是VR"视图+戳记+对戳"结构的变体。旧印的齿纹,錾在了后来每一枚印上。