分解微服务,还是平衡分布式系统的复杂性

3 篇文章 0 订阅
2 篇文章 0 订阅

分解微服务,还是平衡分布式系统的复杂性

著者:Vladik Khononov
 
 
    微服务的蜜月期已经结束了。Uber正在把数千个微服务重构成一个更容易管理的解决方案;Kelsey Hightower又开始预言单体架构就是未来;连Sam Newman(《微服务设计》的作者)都在宣称说微服务不应该是默认首选,而是最后的手段。
    发生什么事情?为什么如此多的项目变得难以维护,尽管微服务承诺简单和灵活?或者说单体架构更加好?
    在这篇文章里,我想解答这些问题。你将会了解到从微服务转变成分布式大泥球所遇到的一些问题,当然你能避免它们。
    首先,我们一起来澄清一下什么是单体。
 
单体
 
    微服务总是被定位为单体代码库的一个解决方案。但是,单体应用一定有问题吗?根据维基百科的定义,一个单体应用是自包含并独立于其他计算机应用。独立于其他应用?这不正是我们在设计微服务时候所追求的吗?David Heinemeier Hansson马上疾呼抹黑单体应用,他警告说分布式系统天生的可靠性和挑战,并使用Basecamp来证明一个服务于数百万客户的大型系统也是可以通过一个单体代码库实现和维护。
    因此,微服务没有解决掉单体。真正的问题是微服务应该解决的真正问题是无法交付业务目标。通常,团队之所以不能实现业务目标,是因为变更成本呈指数级增长,或者更糟糕的是成本不可预测。换句话说,系统无法跟上业务需求的节奏。不受控的变更成本不是单体应用的属性,而是一个大泥球。
 
大泥球是一个杂乱结构的、松散的、带一堆管道或补丁、意大利面式风格的丛林(暗指危险地带)。这类系统展示出不受控的增长和重复性的临时修复等明显迹象。信息在系统中的相互远离的元素间共享,常常达到差不多所有重要信息变成全局性或者重复性的程度。
变更或者演进一个大泥球的复杂性可有由多个因素所引起:协调多个团队的工作、相互冲突的非功能性需求、或者是一个辅助的业务领域。无论如何,我们经常试图通过把这种笨拙的解决方案分解成微服务来解决这种复杂性。
 
微什么?
 
    “微服务”这个名词暗示着一个服务的某部分能够被度量,并且它的价值应该被最小化。但是,微服务究竟意味着什么?让我们看看这个词的集中常见用法。
 
微团队
    第一个是服务团队的规模。这个标准应该用披萨来度量。严肃的说,如果一个服务团队可以用两个披萨来填饱肚子,那么这就是微服务。我发现这真是一种富含启发性的传闻,因为我曾经和一个能被一个披萨喂饱的团队一起建设过一个项目,而且我敢说没人敢把那些泥球称为微服务!
 
微代码库
    另一种广泛使用的方法是根据代码库的大小来设计微服务。有些人将这个概念发挥到了极致,试图将服务大小限制在一定数量的代码行。也就是说,组成一个微服务所需的确切行数还有待去发现。而一旦这个软件架构的圣杯被发现,我们将进入下一个问题——构建微服务的推荐编辑器的宽度是什么?
    更严肃地说,这种方法的一个不那么极端的版本是最流行的。代码库的大小通常被用作判断是否微服务的一个富含启发性的方法。
    在某种程度上,这种方法是讲得通的。因为代码库越小,业务域的范围就越小。因此,它更容易被理解、实现和演进。此外,更小的代码库转变成一个大的泥球的机会更少。如果它确实发生了,那么重构就更简单了。
    不幸的是,上述的简单性只是一种幻觉。当我们基于服务本身评估服务的设计时,我们忽略了系统设计的一个关键部分。我们忘记了系统本身,就是那个服务只是其中一个组件的那个系统。
    
定义服务的边界有许多有用的启发方法。大小是最没用的。——Nick Tune
 
我们建设系统
 
    我们建设的是系统,而不是一堆服务。我们利用微服务架构来优化一个系统设计,而不是设计一堆独立的服务。不管其他人怎么说,微服务不能,并且将来也永远既不能被完全解耦,也不能完全独立。你不能使用独立的组件来构建一个系统,因为那违背了“系统”的定义。
 
1. 一组连接在一起的事物或设备
2. 一套用于特定目的的计算机设备和程序
 
    服务之间总是会互相交互而形成一个系统。如果你通过优化它的服务但是却忽视他们之间的交互设计来设计这个系统的话,以下就是你将会见到的一个局面。
    
    

 

        这些“微服务”可能单独很简单,但是系统本身就是一个复杂的地狱!那么我们如何设计微服务来处理服务和系统级别的复杂性呢?这是一个很难回答的问题,但幸运的是这个问题很久以前就有人回答了。

 
关于复杂性的系统性视角
 
    四十年前,没有云计算,没有全球范围的需求,也不需要每11.7秒部署一个系统。但是,工程师们仍然不得不驯服系统的复杂性。尽管当时的工具有所不同,但现在的挑战(更重要的是解决方案)都是相关的,可以应用到基于微服务的系统设计中。
    在Glenford J. Myers的书《复合/结构化设计》中,讨论到如何构造过程代码以减少其复杂性。在该书的第一页写道:
 
There is much more to the subject of complexity than simply attempting to minimize the local complexity of each part of a program. A much more important type of complexity is global complexity: the complexity of the overall structure of a program or system (i.e., the degree of association or interdependence among the major pieces of a program)。
    在我们的上下文中,所谓的局部复杂性就是每个微服务的复杂性,而全局复杂性是整个系统的复杂性。局部复杂性取决于服务如何实现,而全局复杂性则是由服务间的交互和依赖关系所定义的。
    那么,哪种复杂性更重要,局部复杂性还是全局复杂性?让我们看看当只处理其中一种复杂性时会发生什么。
    将全局复杂性最小化是非常容易的,我们所要做的就是消除系统各组成部分之间的相互作用,例如直接在一个单体服务中实现所有的功能。正如我们前面看到的,这种策略在某些情况下可能有效。在另一些地方,它可能会导致可怕的大泥球,即可能是局部复杂性的最高级别。
    另一方面,如果只优化局部复杂性,而忽略了系统的全局复杂性,即更可怕的分布式大泥球,那我们知道将会发生什么。
    
    
 
    因此,如果我们只关注其中一种复杂性,那么选择哪一种已经不重要了。在一个非常复杂的分布式系统中,相反的那个复杂性会陡增(如果只优化一个的话)。因此,我们不能只优化一个,相反地我们必须平衡局部复杂性和全局复杂性。
    有趣的是,《复合/结构化设计》一书描述的平衡复杂性的办法不仅仅跟分布式系统有关,他们还提供如何设计微服务的见解。
 
微服务
    让我们来准确定义我们正在讨论的那些服务和微服务是什么吧。
 
    什么是服务?
    根据OASIS标准,一个服务是一种允许通过规定的接口的方式来访问一个或多个功能的机制。
    
    规定的接口部分是很关键的,因为一个服务接口定义了它向外界提供的功能。根据Randy Shoup的说法,服务的公共接口说白了就是从服务中获取或提供数据的一个简单机制。它可以是类似普通的请求/响应模型的同步模式,也可以是像生产与消耗的事件驱动的异步模式。不管是同步的还是异步的,公共接口只是一个将数据输入或输出的方法。Randy还将服务的公共接口描述为它的前门。
 
    服务是由其公共接口定义的,这个定义足以定义是什么使服务成为微服务。
 
微服务是什么?
 
    如果一个服务是被它的公共接口所定义的话,那微服务就是一个带有微公共接口(微前门)的一个服务。
    这个简单的启发在过程式编程时代就已经被采用了,而且它在分布式系统领域非常重要。你所暴露的公共服务越小,其实现就越简单,其局部复杂性就越低。从全局复杂性的角度来看,越小的公共接口在服务之间产生更少的依赖和连接。
 
    微接口的概念也说明了微服务不暴露其内部数据库的广泛实践。任何微服务都不能直接访问另一个微服务的数据库,而只能通过它的公共接口。这是为什么呢?好吧,数据库将是一个巨大的公共接口!只需考虑一下你在关系数据库上可以执行各种各样的操作。
 
    因此,重申一下,在分布式系统中,我们通过最小化服务的公共接口来平衡本地和全局复杂性,从而使它们成为微服务。
 
警告
 
    这种启示听起来似乎很简单。如果一个微服务只是一个具有微公共接口的服务,那么我们可以将公共接口限制为只有一个方法。既然前门不能再小了,那就应该是完美的微服务,对吧?其实不然。为了说明为什么,我将使用我的另一篇关于这个主题的文章中的例子:
 
    这里我们假设有以下的backlog management服务:
 
    一旦我们把它解耦成8个服务,每个有一个单一公共方法,那我们就得到那些具有完美局部复杂性的服务。
 
    
    但是我们可以将它们拼接在到实际管理backlog的系统中吗?其实不然。为了形成系统,服务间必须彼此交互并共享对每个服务状态的更改。但它们不能,因为它们的公共接口不支持这一点。
    因此,我们必须使用支持服务之间集成的公共方法来扩展这个前门。
 
    
 
    Boom。如果我们只是单独地优化每个服务的复杂性(即局部复杂性),那么简单的分解就可以工作得很好。然而,当我们试图将服务连接到系统中时,全局复杂性就会引入。结果是系统不仅变成一个纠缠不清的烂摊子,而且为了集成我们还必须扩展公共接口,而这是超出(或者说违背)我们最初的意图。改述一下Randy Shoup的话,除了小小的前门,我们创造了一个巨大的“员工专用”通道,而这会引出了一个重要的问题:
    对分布式大泥球来说,一个服务里面它具有为集成而引入的方法比业务方法更多的话,这本身就是极具启发性的。
    因此,使服务的公共接口最小化的阈值不仅取决于服务本身,而且主要取决于服务所属的系统。对微服务的适当分解应该综合平衡系统的全局复杂性和其服务的局部复杂性。
 
设计服务边界
    
    Udi Dahan曾经说过:“发现服务边界是真的很难,这里没有流程图。”。
    
    上述说法对于基于微服务架构的系统尤其正确。设计微服务的边界是困难的,而且可能无法在第一次就做好。这使得设计一个相当复杂的基于微服务的系统成为一个迭代过程。
 
    因此,更安全的做法是从更宽的边界入手(可能是适当的有界上下文的边界),然后随着对系统及其业务领域获得更多知识再将它们逐步分解为微服务,这与包含核心业务域的服务尤其相关。
 
分布式系统以外的微服务
 
    即使微服务是最近才“发明”出来的,你也可以在其他行业找到大量相同设计原则的实践。这些简单的理念包括:
    
跨职能团队
    我们都知道跨职能团队是最有效的团队,这样的团队是由为了完成同一个任务而由不同专业人员组成的。这样一个高效的跨职能团队能够最大化团队内部的沟通和最小化团队外部的沟通。
 
    我们的行业最近才发现了跨职能团队,但是任务组已经存在很久了。这些的基本原则与基于微服务的系统的基本原则相同:团队内部的高内聚性和团队之间的低耦合。团队的“公共接口”通过将完成任务所需的技能纳入团队(即实现细节)。
 
微处理器
    我在Vaughn Vernon关于同一主题的精彩博客中偶然发现了这个例子。在他的文章中,Vaughn将微服务和微处理器进行了有趣的对比。他特别讨论了处理器和微处理器之间的区别:
我发现一个有趣的现象,这里有一个给定的大小分类来帮助确定一个中央处理器(CPU)是否被认为是一个微处理器,这就是它的数据总线的大小。
 
    微处理器的数据总线是它的公共接口——它定义了微处理器和其他组件之间可以传递的数据量。公共接口有一个严格的大小分类,它定义了一个中央处理单元(即CPU)是否被认为是微处理器。
 
Unix哲学
    Unix哲学,或者说Unix方式,是一组文化规范和哲学方法,用于抽象化、模块化的软件开发。
 
    有人可能会说,Unix的哲学与我的观点相矛盾,即不能用完全独立的组件来构建一个系统。难道Unix程序不是完全独立的吗?事实正好相反,Unix方式几乎总是定义程序必须暴露微交互。让我们看看Unix哲学的原则如何与微服务的概念相呼应。
 
    第一个原则要求程序的公共接口必须暴露一个高内聚的功能,而不是用与原始目标毫不相干的功能来把程序弄得一团糟。
目标:让每个程序都做好一件事。要完成一项新的工作,应该重新构建而不是通过添加新的“特性”使旧的程序变得复杂。
    
    即使Unix命令之间被认为完全互相独立,实际上它们不是。它们仍然必须与其他通讯。还有,第二个原则定义了通讯接口应该被如何设计:
期望每个程序的输出成为另一个未知程序的输入。不要用无关的信息干扰输出,避免严格的列或二进制输入的格式,不要坚持交互式输入。
    不仅通信接口受到严格的限制(标准输入、标准输出和标准错误),而且根据这个原则,在命令之间传递的数据也应该受到严格的限制。例如,Unix命令必须公开微接口,并且永远不能依赖于彼此的实现细节。
 
Nano-Service(纳米服务)又怎样?
 
    术语“nanoservice”通常用来描述规模非常小的服务。有人会这样说,前面示例中那些简单的单方法服务就是纳米服务。然而,我并不一定同意这种分类。
 
    纳米服务被用来描述单个服务而忽略了系统的整体性。在上面的例子中,一旦我们将系统放入等式中,服务的接口就必须增长。事实上,如果我们将原始的单服务实践与简单的分解进行比较,我们可以看到,一旦我们将服务连接到一个系统中,整个系统的公共方法将会从8个增加到38个。此外,每个服务的公共方法的平均数量会从期望的1个变成4.75个。
 
    因此,如果我们优化服务的公共接口而不是优化代码库,术语纳米服务将不再适用,因为服务将被迫重新变大以支持其系统的用例(暗指支持系统的整体功能)。
 
就这些吗?
 
    不。虽然最小化服务的公共接口对于微服务设计来说是一个很好的指导原则,但它仍然只是一种启示但并不能取代常识。实际上微接口只是一种抽象,它涵盖了更基本、但更复杂的耦合和内聚设计原则。
 
    例如,如果两个服务具有微公共接口,但是它们必须在分布式事务中进行协调,它们之间仍然是高度耦合的。
 
    也就是说,以微接口为目标仍然是解决不同类型耦合(如功能耦合、开发耦合和语义耦合)的一种强大的启示,但这就是另一个话题。
 
从理论到实践
 
    不幸的是,我们还没有一个客观的方法来量化局部和全局复杂性。另一方面,我们确实有一些设计启发可以用来改进分布式系统的设计。
 
    这篇文章的主要想表达的是你应该通过提出以下问题来不断地评估你的服务的公共接口:
 
    1、在给定的服务中,面向业务和面向集成的端点的比例是多少?
    2、服务中是否存在业务上不相关的端点?您能否在不引入面向集成的端点的情况下将它们拆分为两个或多个服务?
    3、合并两个服务是否会消除由于集成原始服务所引入的端点吗?
 
    请使用这些启示来指导服务边界和接口的设计。
 
总结
 
    我想通过 Eliyahu Goldratt 的一个观察来总结这一切。在他的书中,他反复提到:告诉我你如何度量我,那我会告诉你我如何表现。
 
     在设计基于微服务的系统时,测量和优化正确的度量是至关重要的。为微代码库和微团队设计边界肯定更容易。然而,要建立一个系统,我们必须考虑它。微服务是关于设计系统的,而不是设计单独服务的。
 
    这又把我们带回到文中的标题:“分解微服务,还是平衡分布式系统的复杂性”。解决微服务的唯一方法是平衡每个服务的局部复杂性和整个系统的全局复杂性。
!!注意:全文有99M,由于上传文件不得超过60M,所以分成两个压缩文件,这是part1.part2在以下网页: http://download.csdn.net/detail/hellowjl1/4682120 在本书中,作者给出设计,实现和分析分布式算法的蓝图。本书适合学生、程序员、系统分析员和研究人员等不同类型的读者。本书包括这个领域最重要的算法和不可能解.而且都采用简单的自动机理论进行论述。对所有算法的正确性都给予证明.并且根据精确定义的复杂度标准分析算法的复杂度。其中涉及的问题包括资源分配、通信、分布式处理器之间的一致性、数据一致性、死锁检测、领导者进程的选取、全局快照等。    本书的内容按照系统模型组织,首先是根据定时模型.然后在定时模型内再根据进程间的通信机制。不同系统的材料分别独立成章,便于查阅。    本书论述十分严谨,但又很直观.便于读者迅速理解。本书也为读者提供设计新的算法和证明新的不可能解的基本数学工具。而且,它教给读者怎样对分布式系统进行严格的推理 ―包括形式化建模,为它们所需的行为设计精确的指标,证明它们的正确性.并且用实际的度量标准来评价它们的性能。    本书对分布式算法进行全面介绍,包括最为重要的算法和不可能性结果。绝大部分的解都给出了数学证明。这些算法都根据精确定义的复杂度衡量方法进行分析。本书还讲述针对许多典型问题的算法、各类系统模型及其能力。章后提供大量习题并列出了详细的参考文献。    本书可作为高等院校计算机系研究生的教材,尤其适合对计算机理论或体系结构感兴趣的学生学习,还适合分布式设计人员、研究人员及其相关技术人员参考。 出版者的话 专家指导委员会 译者序 前言 第1章 引言 1 1.1 相关主题 1 1.2 我们的观点 2 1.3 本书内容综述 3 1.4 参考文献注释 7 1.5 标记 7 第一部分 同步网络算法 第2章 建模i:同步网络模型 10 2.1 同步网络系统 10 2.2 故障 11 2.3 输入和输出 11 2.4 运行 11 2.5 证明方法 12 2.6 复杂度度量 12 2.7 随机化 12 2.8 参考文献注释 13 .第3章 同步环中的领导者选择 14 3.1 问题 14 3.2 相同进程的不可能性结果 14 3.3 基本算法 15 3.4 通信复杂度为o(n log n)的算法 17 3.5 非基于比较的算法 19 3.5.1 时间片算法 20 3.5.2 变速算法 20 3.6 基于比较的算法的下界 21 3.7 非基于比较的算法的下界* 25 3.8 参考文献注释 26 3.9 习题 27 第4章 一般同步网络中的算法 29 4.1 一般网络中的领导者选举 29 4.1.1 问题 29 4.1.2 简单的洪泛算法 29 4.1.3 降低通信复杂度 31 4.2 广度优先搜索 32 4.2.1 问题 32 4.2.2 基本的广度优先搜索算法 33 4.2.3 应用 34 4.3 最短路径 35 4.4 最小生成树 36 4.4.1 问题 36 4.4.2 基本定理 36 4.4.3 算法 37 4.5 最大独立集 39 4.5.1 问题 40 4.5.2 随机化算法 40 4.5.3 分析* 42 4.6 参考文献注释 43 4.7 习题 43 第5章 链路故障时的分布式一致性 46 5.1 协同攻击问题―确定性版本 46 5.2 协同攻击问题―随机化版本 48 5.2.1 形式化模型 49 5.2.2 算法 49 5.2.3 不一致的下限 52 5.3 参考文献注释 54 5.4 习题 54 第6章 进程故障下的分布式一致性 56 6.1 问题 56 6.2 针对停止故障的算法 58 6.2.1 基本算法 58 6.2.2 减少通信 59 6.2.3 指数信息收集算法 61 6.2.4 带鉴别的byzantine一致性 66 6.3 针对byzantine故障的算法 66 6.3.1 举例 66 6.3.2 byzantine一致性问题的eig算法 68 6.3.3 使用二元byzantine一致的一般 的byzantine一致性问题 71 6.3.4 减少通信开销 72 6.4 byzantine一致性问题中进程的个数 74 6.5 一般图中的byzantine一致性问题 78 6.6 弱byzantine一致性 81 6.7 有停止故障时的轮数 82 6.8 参考文献注释 88 6.9 习题 89 第7章 更多的一致性问题 93 7.1 k一致性问题 93 7.1.1 问题 93 7.1.2 算法 93 7.1.3 下界* 95 7.2 近似一致性 102 7.3 提交问题 105 7.3.1 问题 105 7.3.2 两阶段提交 106 7.3.3 三阶段提交 107 7.3.4 消息数的下界 109 7.4 参考文献注释 111 7.5 习题 111 第二部分 异步算法 第8章 建模ii:异步系统模型 114 8.1 输入/输出自动机 114 8.2 自动机的操作 118 8.2.1 合成 118 8.2.2 隐藏 121 8.3 公平性 121 8.4 问题的输入和输出 123 8.5 属性与证明方法 124 8.5.1 不变式断言 124 8.5.2 轨迹属性 124 8.5.3 安全与活性属性 125 8.5.4 合成推理 126 8.5.5 层次化证明 128 8.6 复杂度衡量 130 8.7 不可区分运行 131 8.8 随机化 131 8.9 参考文献注释 131 8.10 习题 132 第二部分a 异步共享存储器算法 第9章 建模iii:异步共享存储器模型 136 9.1 共享存储器系统 136 9.2 环境模型 138 9.3 不可区分状态 140 9.4 共享变量类型 140 9.5 复杂度衡量 144 9.6 故障 144 9.7 随机化 145 9.8 参考文献注释 145 9.9 习题 145 第10章 互斥 146 10.1 异步共享存储器模型 146 10.2 问题 148 10.3 dijkstra的互斥算法 151 10.3.1 算法 151 10.3.2 正确性证明 154 10.3.3 互斥条件的一个断言证明 156 10.3.4 运行时间 157 10.4 互斥算法的更强条件 158 10.5 锁定权互斥算法 159 10.5.1 双进程算法 159 10.5.2 n进程算法 163 10.5.3 锦标赛算法 167 10.6 使用单写者共享存储器的算法 170 10.7 bakery算法 171 10.8 寄存器数量的下界 173 10.8.1 基本事实 174 10.8.2 单写者共享变量 175 10.8.3 多写者共享变量 175 10.9 使用读-改-写共享变量的互斥 179 10.9.1 基本问题 179 10.9.2 有界绕过次数 180 10.9.3 锁定权 185 10.9.4 模拟证明 187 10.10 参考文献注释 189 10.11 习题 190 第11章 资源分配 194 11.1 问题 194 11.1.1 显式资源说明和互斥说明 194 11.1.2 资源分配问题 195 11.1.3 哲学家用餐问题 196 11.1.4 解法的受限形式 197 11.2 对称哲学家用餐算法的不存在性 197 11.3 右-左哲学家用餐算法 199 11.3.1 等待链 199 11.3.2 基本算法 200 11.3.3 扩展 202 11.4 哲学家用餐随机算法* 204 11.4.1 算法* 205 11.4.2 正确性* 207 11.5 参考文献注释 212 11.6 习题 213 第12章 一致性 215 12.1 问题 215 12.2 使用读/写共享存储器的一致性 217 12.2.1 限制 218 12.2.2 术语 218 12.2.3 双价初始化 218 12.2.4 无等待终止的不可能性 219 12.2.5 单故障终止的不可能性结果 221 12.3 读/改/写共享存储器上的一致性 问题 223 12.4 其他共享存储器类型 224 12.5 异步共享存储器系统中的可计算性* 224 12.6 参考文献注释 225 12.7 习题 226 第13章 原子对象 229 13.1 定义和基本结论 229 13.1.1 原子对象的定义 229 13.1.2 规范无等待原子对象自动机 235 13.1.3 原子对象的合成 237 13.1.4 原子对象和共享变量 237 13.1.5 显示原子性的一个充分条件 241 13.2 用读/写变量实现读-改-写原子对象 242 13.3 共享存储器的原子快照 243 13.3.1 问题 243 13.3.2 带无界变量的一个算法 244 13.3.3 带有界变量的一个算法* 247 13.4 读/写原子对象 250 13.4.1 问题 250 13.4.2 证明原子性的其他引理 250 13.4.3 带无界变量的一个算法 251 13.4.4 两个写者的有界算法 254 13.4.5 使用快照的算法 258 13.5 参考文献注释 259 13.6 习题 260 第二部分b 异步网络算法 第14章 建模iv:异步网络模型 264 14.1 发送/接收系统 264 14.1.1 进程 264 14.1.2 发送/接收通道 264 14.1.3 异步发送/接收系统 268 14.1.4 使用可靠fifo通道的发送/ 接收系统的特征 268 14.1.5 复杂度度量 269 14.2 广播系统 269 14.2.1 进程 269 14.2.2 广播通道 270 14.2.3 异步广播系统 270 14.2.4 采用可靠广播通道的广播系统 的特征 270 14.2.5 复杂度度量 271 14.3 多播系统 271 14.3.1 进程 271 14.3.2 多播通道 271 14.3.3 异步多播系统 272 14.4 参考文献注释 272 14.5 习题 272 第15章 基本异步网络算法 274 15.1 环中的领导者选举 274 15.1.1 lcr算法 275 15.1.2 hs算法 278 15.1.3 peterson leader算法 278 15.1.4 通信复杂度的下界 281 15.2 任意网络中的领导者选举 286 15.3 生成树的构造、广播和敛播 287 15.4 广度优先搜索和最短路径 290 15.5 最小生成树 295 15.5.1 问题描述 295 15.5.2 同步算法:回顾 296 15.5.3 ghs算法:概要 296 15.5.4 更详细的算法 297 15.5.5 特殊消息 299 15.5.6 复杂度分析 301 15.5.7 ghs算法的正确性证明 301 15.5.8 简单“同步”策略 302 15.5.9 应用到领导者选举算法中 302 15.6 参考文献注释 303 15.7 习题 303 第16章 同步器 307 16.1 问题 307 16.2 局部同步器 309 16.3 安全同步器 313 16.3.1 前端自动机 314 16.3.2 通道自动机 315 16.3.3 安全同步器 315 16.3.4 正确性 315 16.4 安全同步器的实现 316 16.4.1 同步器alpha 316 16.4.2 同步器beta 317 16.4.3 同步器gamma 317 16.5 应用 320 16.5.1 领导者选举 321 16.5.2 深度优先搜索 321 16.5.3 最短路径 321 16.5.4 广播与确认 321 16.5.5 最大独立集 321 16.6 时间下界 321 16.7 参考文献注释 324 16.8 习题 324 第17章 共享存储器与网络 326 17.1 从共享存储器模型到网络模型 的转换 326 17.1.1 问题 326 17.1.2 无故障时的策略 327 17.1.3 容忍进程故障的算法 332 17.1.4 对于n/2故障的不可能性结果 335 17.2 从网络模型转换到共享存储器模型 336 17.2.1 发送/接收系统 336 17.2.2 广播系统 338 17.2.3 异步网络中一致性的不可能性 338 17.3 参考文献注释 339 17.4 习题 339 第18章 逻辑时间 341 18.1 异步网络的逻辑时间 341 18.1.1 发送/接收系统 341 18.1.2 广播系统 343 18.2 使用逻辑时间的异步算法 344 18.2.1 时钟的走动 344 18.2.2 延迟未来事件 345 18.3 应用 346 18.3.1 银行系统 346 18.3.2 全局快照 348 18.3.3 模拟一台单状态机器 349 18.4 从实际时间算法到逻辑时间算法 的变换* 352 18.5 参考文献注释 352 18.6 习题 353 第19章 一致全局快照和稳定属性检测 355 19.1 发散算法的终止检测 355 19.1.1 问题 355 19.1.2 dijkstrascholten算法 356 19.2 一致全局快照 360 19.2.1 问题 360 19.2.2 chandylamport算法 361 19.2.3 应用 364 19.3 参考文献注释 366 19.4 习题 367 第20章 网络资源分配 369 20.1 互斥 369 20.1.1 问题 369 20.1.2 模拟共享存储器 370 20.1.3 循环令牌算法 370 20.1.4 基于逻辑时间的算法 372 20.1.5 logicaltimeme算法的改进 374 20.2 通用资源分配 376 20.2.1 问题 376 20.2.2 着色算法 377 20.2.3 基于逻辑时间的算法 377 20.2.4 无环有向图算法 378 20.2.5 哲学家饮水* 379 20.3 参考文献注释 383 20.4 习题 383 第21章 带进程故障的异步网络计算 386 21.1 网络模型 386 21.2 有故障环境中一致性的不可能性 387 21.3 随机算法 388 21.4 故障检测器 390 21.5 k一致性 393 21.6 近似一致性 394 21.7 异步网络的计算能力* 395 21.8 参考文献注释 396 21.9 习题 396 第22章 数据链路协议 399 22.1 问题阐述 399 22.2 stenning协议 400 22.3 位变换协议 403 22.4 可重排序的有界标志协议 406 22.4.1 关于重排序和复制的不可能 性结论 407 22.4.2 容许丢失和重排序的有界标 志协议 408 22.4.3 不存在容许消息丢失和重排序 的高效协议 412 22.5 容许进程崩溃 414 22.5.1 简单的不可能性结论 415 22.5.2 更复杂的不可能性结论 415 22.5.3 实用的协议 418 22.6 参考文献注释 423 22.7 习题 423 第三部分 部分同步算法 第23章 建模v: 部分同步系统模型 428 23.1 mmt 定时自动机 428 23.1.1 基本定义 428 23.1.2 操作 432 23.2 通用定时自动机 434 23.2.1 基本定义 434 23.2.2 将mmt自动机转化为通用定时 自动机 437 23.2.3 操作 440 23.3 属性和证明方法 441 23.3.1 不变式 441 23.3.2 定时轨迹属性 443 23.3.3 模拟 444 23.4 构造共享存储器和网络系统的模型 449 23.4.1 共享存储器系统 449 23.4.2 网络 449 23.5 参考文献注释 449 23.6 习题 450 第24章 部分同步的互斥 452 24.1 问题 452 24.2 单寄存器算法 453 24.3 对时间故障的回复性 459 24.4 不可能性结果 461 24.4.1 时间下界 462 24.4.2 最终时间界限的不可能性结果* 462 24.5 参考文献注释 463 24.6 习题 463 第25章 部分同步的一致性 466 25.1 问题 466 25.2 故障检测器 467 25.3 基本结论 468 25.3.1 上界 468 25.3.2 下界 469 25.4 有效算法 470 25.4.1 算法 471 25.4.2 安全属性 472 25.4.3 活性和复杂度 473 25.5 涉及时间不确定性的下界* 475 25.6 其他结果* 480 25.6.1 同步进程、异步通道* 480 25.6.2 异步进程、同步通道* 481 25.6.3 最终时间界限* 481 25.7 小结 483 25.8 参考文献注释 483 25.9 习题 483 参考文献 486 索引 512
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值