跳转到内容
← 返回系统剖析
系统剖析当代约 21 分钟阅读

ISIS 1985:进程组、flush 与虚拟同步,不是又一份 ZooKeeper

ISIS 1985: Process Groups, Flush, and Virtual Synchrony

ISIS虚拟同步进程组flush容错

1985 年 12 月,康奈尔大学的肯尼斯·伯曼(Kenneth P. Birman)在第十届 ACM SOSP 上交出八页论文,会议录页码 79 至 86,DOI 10.1145/323627.323636。题目是 Replication and Fault-Tolerance in the ISIS System。系统名 Isis 由阿姆尔·埃尔·阿巴迪(Amr El Abbadi)提议,取自埃及复活神话:伊西斯把被撕碎的奥西里斯重新拼起来。伯曼这边要复活的,是被节点崩溃撕开的对象。

对象是 1985 年这篇系统论文交出的装置:进程组、组成员视图、flush,以及后来被称为虚拟同步的那种执行口径——组员看见的事件序列,应当像在一台不故障的机器上同步发生过一样。同年稍早,伯曼与托马斯·约瑟夫(Thomas A. Joseph)等人在 IEEE Transactions on Software Engineering 上写过容错分布式对象;同月前后的康奈尔技术报告 TR85-694 把可靠通信协议写全,1987 年收进 ACM TOCS。名称“虚拟同步”在 1987 年 SOSP 的 Exploiting Virtual Synchrony in Distributed Systems 里被点明。那些是同一条装置的已发表补全,不是把本页兑成工具箱手册。

它不是 ZooKeeper。2010 年那篇 ATC 报告把 sync 比作 ISIS 的 flush,并写明虚拟同步是相关工作;znode、watch 与 Zab 属于那一页。它也不是 视图戳复制 的主副本与盖章请求,不是 《兼职议会》 里选定一个值的 Synod,不是 etcd 或 共识算法 总览里的 Raft 工程。几台机器怎么组成一组、计时器拧到哪一格、如何逼一次成员变更,都不在这篇对象里。

破除误解

  1. 误解**误解一:这篇就是 ZooKeeper 的前身说明书,读懂 flush 就等于读懂 sync、Zab 和短暂节点。

    实情** ZooKeeper 论文自己把 sync 写成“类似 ISIS 的 flush”,那是在相关工作里找类比,不是把 1985 年的八页认成 2010 年的协调内核。ISIS 交给程序员的是进程组与容错对象;ZooKeeper 交给客户端的是等待自由的数据树。flush 要在组成员视图切换之前,把旧视图里尚未了结的组播收束成全体一致的记忆;sync 要让当前连着的那台服务器先把已挂起的更新应用完,再让后续读看见。两边都在付费对齐观察,协议、接口和故障单元都不是同一份。把两个名字叠成一个词,会把进程组换成 znode,把视图换成会话超时。

误解二:虚拟同步就是早几年的 Paxos,或晚一点的 Raft、视图戳复制,换一套角色名而已。 1985 年的文本比《兼职议会》的寓言稿还早,比它刊出早十三年,也比奥基与利斯科夫的 1988 年主副本方法早三年。它要解决的不是“异步网络里如何选定一个客户值”,也不是“主副本怎样给请求盖视图戳”。装置是进程组、当前视图、flush,以及把可能误报的超时怀疑收成全组同一份成员事实。提议者、接受者和选票编号不在这八页里。Garcia-Molina 1982 的霸道选举比较的是预先写好的整数编号;ISIS 的协调者—同组伙伴(coordinator-cohort)按请求指派执行者,崩溃后由同组伙伴接过,并不靠“谁的编号更大谁就赢”。后来的对照文献可以把虚拟同步、Paxos 与 Zab 放在一张表上;对读不是兑成同一份伪代码。

误解三:进程组不过是一份组播通讯录,V 内核里已经有了,这篇只是换了个容错形容词。 同年切里顿与兹瓦内普尔(Cheriton & Zwaenepoel)在 ACM TOCS 上写出 V 内核的分布式进程组,强调网络层需要一种公共的组通信原语。那份对象管的是寻址与投递,并不给出复制模型,也不把“谁还算活着”收成全组必须同意的视图。ISIS 把组当成被复制的对象:加入时做状态转移,成员变更时安装新视图,组播相对于视图有顺序。没有这份视图,组播名册只是一份可能每人各看各的列表。把 1985 年这篇读成 IP 组播的用户手册,会丢掉它真正要卖的那一层——组成员本身必须是一份可信任的共同记忆。

误解四:flush 就是把磁盘刷干净,或者就是一次超时;视图变更就是故障切换脚本。 存储栈里的 flush 是介质顺序。ISIS 的 flush 是组通信上的收束:在安装新视图、或在需要更强投递口径之前,先让当前视图里已经发出的消息,对还活着的成员达成一致的交付或一致的放弃。它不是计时器配方,也不是教人如何把某个成员从组里挤出去。视图变更要保证:同一条组播不会在两个不同视图里被交付;还活着的成员看见同一串视图;新成员靠状态转移接到当前组状态,而不是带着空白内存冒充上一届。FLP 同年标明完全异步里慢与死没有可检验的分界;论文把超时怀疑交给组成员服务去虚拟化,并不声称推翻那条不可能性。计时器拧到哪一毫秒,怎样制造一次分区,都不在纸上的装置里。

进程组、flush 与虚拟同步

ISIS 第一版按当时的主流做成翻译器:程序员用接近 Argus、Clouds 的对象语言写出一个对象,系统把它变成可以在多台机器上同时活着的容错实现。外界看见的是一个逻辑对象;内部是若干代表。论文把复制方案叫做协调者—同组伙伴。一次调用进来,由一名代表当协调者执行,其余当同组伙伴接收同一份输入、准备接过。协调者崩溃,同组伙伴中的一名接替。不同调用可以把协调者角色摊到组里不同的成员上,因而不是“永远只有一台主副本、其余只收日志”的固定主备。对象按能扛住几次崩溃来标:要在 \(k\) 次故障后仍在,至少需要 \(k+1\) 份代表。故障模型明确不是拜占庭:节点按停止崩溃,网络可丢失与延迟。这是崩溃停止加上一份被虚拟化的成员事实,不是恶意节点可以任意撒谎的模型。

进程组是这套复制的住所。组可以有名字,成员加入、退出、被判定离开,都会留下一次视图变更。所有成员保证看见同一份视图内容:此刻谁在组里、成员排序、触发这次变更的事件。新成员加入时,平台向一名已有成员要一份组状态检查点,送给加入者初始化——状态转移必须和组播排成全组一致的顺序,不能让一条组播卡在“半个成员已在、半个成员还不在”的缝里。组播不必事先知道当前成员名单;投递必须落在“正确”的那一届视图上。读可以信任本地副本,正因为视图已经被当成全组同意的事实:每个还在视图里的成员,都应当已经接到先前的更新。这是相对静态法定人数算法的性能论证,不是把三台机器摆进机架的作业。

组成员服务把“我怀疑他停了”收成全组同一句话。当时多数网络程序在传输层各自用等待判断对方死活,于是同一场短暂中断里,有人切断连接、有人还以为对方在。ISIS 不让单机私自把怀疑写成结局:超时怀疑被送到一份本身也复制的成员服务,由它向全体回显“从现在起,把某人当作已经停机”。被点名的进程若其实还活着,必须像新启动的进程一样重新加入、重新做状态转移,不能凭自己手里那份旧视图继续说话。新视图要在上一届的多数明确同意之后才能安装。发起者是当时仍被当作活着的、资格最老的成员服务进程;领导者仍被信任时走两阶段提交,领导者自己也被怀疑时改走三阶段,以免提交在换人时卡住。这些手续写在同月的技术报告里,SOSP 的八页管系统问题与原型表现。多数同意与主分区约束是正确性声明:同一时刻只允许一个主分区继续推进视图。不是一份教人如何拆开成员服务、如何用等待逼一次换届的说明。

flush 是视图与组播之间的那道收束。调用它的进程要等到:当前视图里应当在此次收束之前交付的消息,已经对还活着的成员有了一致结局。然后才安装新视图,或才把需要更强口径的观察交给应用。默认的组播可以在消息尚不稳定时就投递给应用——若随后发送者崩溃,这条消息可能从幸存者的历史上消失。论文把更强的、接近“一人看见则全体看见”的口径留给显式的 flush,或留给更重的组播原语。ZooKeeper 后来拿 sync 来比的,正是这种“先把未了结的更新收束,再让后面的读开口”的同步点。两边相似的是付费对齐,不是报文格式。把 flush 读成磁盘命令,或读成可以拿来打断别人成员身份的开关,都离开了纸上的装置。

虚拟同步说的是:对外可以假装这些事是同步发生的。真实运行里,消息到达时刻并不整齐;只要组员无法分辨差别,实现就可以把可交换的事件按更便宜的顺序交付。组员因此能够维护一份彼此等价的组状态,而不必在每一次投递上都锁步。1985 年交出的正是让这句承诺能落地的装置:有视图,才知道“当前成员”是谁;有 flush,才知道旧视图里的消息不会漏进新视图;有状态转移,新来的人才不会从空白内存开始投票。1987 年的论文把这句承诺收成一个名字,并开始讲工具箱 API。本页停在 1985 年:对象是容错复制系统里的组、视图与 flush,不是后来的因果组播优化,也不是把进程组当成可采购中间件来部署。

论文表明了什么,以及它没有表明的东西

它表明复制不必先让每个客户端自己用超时判决“宕机还是慢”。把成员事实收成全组同一份视图,本地读才有资格信任自己手里的副本;更新可以发给“当前成员”,而不必每次都向一张静态名单做法定人数散射。协调者—同组伙伴表明:容错计算不必永久绑死一台主副本,请求级的执行者可以在组内轮换,崩溃后由已经见过同一输入的伙伴接过。flush 表明:视图变更与组播之间需要一道显式的收束,否则“谁还在组里”和“哪条消息算已经发生”会互相拆台。崩溃停止、分区最终结束、被误判的进程愿意重新加入,是模型假设,不是现场统计。

它没有后来工程报告里那种生产曲线,没有每秒事务数,也没有选举毫秒分布。八页讨论原型表现,并不把数字写成可外推的容量规划。它不处理拜占庭故障。它没有证明自己与后来刊出的 Paxos 形式等价——那是更晚对照文献的事。它也不把 1987 年工具箱、1991 年轻量因果组播、或后来的 Horus 与 Ensemble 写进这八页。事务隔离在第一版对象语言里留下的摩擦,是作者事后承认的设计负担,不是一份已经完成的数据库引擎。

分布式系统 里高可用常被听成“多放几台、组播一下就行”。这篇对象更窄:能继续代表这个组说话的,是仍在主分区视图里、并且已经接到状态转移的那些成员;能被后续视图继承的,是 flush 收束之后仍在的消息。把它读成 ZooKeeper 的操作说明,或读成 Raft、视图戳复制 的选主组件,都离开了 1985 年纸上的装置。

跨域连接

  • 可靠性工程:故障单元不是“这一台还能不能 ping 通”,而是“当前视图是否仍把某人算作成员、以及旧视图里的组播是否已经 flush 收束”。各端私自用等待切断连接,会得到互相矛盾的活着名单;论文把怀疑交给组成员服务,把误判写成“必须重新加入”,而不是允许一份过期视图继续代表组。主分区约束保护的是“同一时刻只有一届在立法”,不是保证每一台机器都一直在线。状态转移把新成员的空白内存标成不可用,直到检查点到达。这是把失效模式写进组手续,不是把超时填进配置文件的作业。
  • 信息不对称:协调者先看见调用的效果,同组伙伴按组播落后。flush 是付费把私有观察收成当前视图里的共同记忆;未收束的消息在换届后可以消失,于是默认组播允许不稳定投递,需要更强口径的人必须显式开口。被误判离开的进程不能凭自己手里那份旧名单继续说话,等于禁止用一份别人已经作废的私有知识冒充组状态。ZooKeeper 的 sync 后来对付的是另一处不对称——本地读可以略旧——类比的是这同一种“先对齐、再引用”,不是同一条报文。
  • 立法机构:视图像必须凑够法定人数才能开会的届次,视图标识像全序的会期。纪要不是全球日历,而是“本届哪些组播已经交付、哪些必须在散会前 flush 掉”。新一届要拿到上一届收束之后的状态来开场,以免已通过的决议消失。新议员靠状态转移宣读当前法律,不能带着空白笔记本投票。比喻能讲清出缺、届次和纪要,不能把这份方法读成《兼职议会》里的提案与选票,也不能读成可采购的议事规则。法定人数保护的是“已被主分区听见的事件不丢”,不是保证每一次换届都会在有限时间内开成。
  • 认识论:组状态里的对象是世界里的事实;视图是一份关于知识的声明——“我们同意,当前这些进程是还在场的观察者”。flush 问的是:在更换观察者名单之前,尚未公开的观察是否已经变成公共知识,或者已经一致地作废。作废了就不能再当已知;公开了就必须被新名单继承。默认组播允许把尚未稳定的消息交给应用,等于明确承认“真尚未知”可以短时间存在于即将崩溃的那个进程里;需要把它收成公共知识时,才额外付一次 flush。工程事故常发生在把协调者内存里尚未收束的效果,当成已经可向全组引用的知识。
  • 概率论:\(k\) 次故障对应至少 \(k+1\) 份代表,多数派按上一届视图来数,而不是按随机图上的渗流阈值来数。可用性论证依赖崩溃与分区最终结束,以及相关故障不会把主分区同时拿走——这是模型假设,不是独立故障乘积公式里的年可用性。被误判的进程按新成员重新加入,处理的是成员事实的唯一性,不是误报率的最大似然估计。八页里的原型数字是一次实现的表现,文中没有到达过程的拟合,也没有把三台与五台画成可外推的可靠度曲线。

参考文献

  • Birman, K. P. Replication and Fault-Tolerance in the ISIS System. Proc. 10th ACM SOSP, 1985, pp. 79–86. doi:10.1145/323627.323636(本文对象)
  • Birman, K. P., Joseph, T. A., Räuchle, T. & El Abbadi, A. Implementing Fault-Tolerant Distributed Objects. IEEE Transactions on Software Engineering 11(6), 1985, pp. 502–508.(同年容错对象;协调者—同组伙伴的语言层前身)
  • Birman, K. P. & Joseph, T. A. Reliable Communication in the Presence of Failures. Cornell University TR85-694, August 1985;ACM TOCS 5(1), 1987, pp. 47–76.(组成员与可靠组播协议的补全文本)
  • Birman, K. P. & Joseph, T. A. Exploiting Virtual Synchrony in Distributed Systems. Proc. 11th ACM SOSP, 1987, pp. 123–138.(把虚拟同步收成名称;非本文对象)
  • Cheriton, D. R. & Zwaenepoel, W. Distributed Process Groups in the V Kernel. ACM TOCS 3(2), 1985, pp. 77–107.(同年进程组:寻址与投递,无本文的复制与视图模型)
  • Skeen, D. Nonblocking Commit Protocols. Proc. ACM SIGMOD, 1981, pp. 133–142.(成员服务在领导者被怀疑时改走的三阶段提交前身)
  • Schneider, F. B. Fail-stop processors: An approach to designing fault-tolerant computing systems. ACM TOCS 1(3), 1983, pp. 222–238.(崩溃停止模型;本文用组成员服务去逼近它)
  • Fischer, M. J., Lynch, N. A. & Paterson, M. S. Impossibility of Distributed Consensus with One Faulty Process. J. ACM 32(2), 1985, pp. 374–382.(完全异步下慢与死不可分;论文不声称推翻)
  • Lamport, L. Time, Clocks, and the Ordering of Events in a Distributed System. Communications of the ACM 21(7), 1978, pp. 558–565.(状态机复制的思想来源;本文把它改写到动态进程组与异步网络)
  • Hunt, P., Konar, M., Junqueira, F. P. & Reed, B. ZooKeeper: Wait-free Coordination for Internet-scale Systems. Proc. USENIX ATC, 2010.(把 sync 比作 ISIS 的 flush;虚拟同步为相关工作,非本文对象)

延伸阅读

  • Birman, K. P., Schiper, A. & Stephenson, P. Lightweight Causal and Atomic Group Multicast. ACM TOCS 9(3), 1991, pp. 272–314.(后来的因果与全序组播优化;非 1985 年对象)
  • Chockler, G. V., Keidar, I. & Vitenberg, R. Group Communication Specifications: A Comprehensive Study. ACM Computing Surveys 33(4), 2001, pp. 427–469.(组通信规格的后设对照)
  • van Renesse, R., Schiper, N. & Schneider, F. B. Vive la Différence: Paxos vs. Viewstamped Replication vs. Zab. IEEE Transactions on Dependable and Secure Computing 12(4), 2015, pp. 472–484.(后来的形式对照,不是把三份兑成一份操作单)
  • Birman, K. P. A History of the Virtual Synchrony Replication Model. In Replication: Theory and Practice, Springer LNCS 5959, 2010, pp. 91–120.(作者回顾:1985 年系统问题、随后的命名与工具箱)
  • 与 ZooKeeper 对读:那一页是等待自由的 znode 与写全序;本文停在 1985 年的进程组、视图与 flush。
  • 与 视图戳复制、兼职议会与 Paxos、共识算法、etcd 对读:那些页讲主副本盖章、选定值与复制日志;本文停在组视图上的虚拟同步。
  • 与 FLP、Garcia-Molina 1982 对读:不可能性标定完全异步的全称承诺;霸道选举在超时假设下比较编号。本文在崩溃停止与主分区模型里谈视图,不把超时写成攻击步骤。