在本系列第一篇文章中咱们提到了Lamport Clock如何启发人们在分布式系统中开始使用新的的思惟方式, 并介绍了Sequential Consistency和Linearizability. 本篇为分布式系统一致性发展的第二篇长文,会介绍他们所延展出来的一些应用问题,让你们更好的理解这两种一致性模型。算法
在本篇正式开始以前, 咱们先定义一下分布式系统中的网络和故障的模型, 这部分稍微有点枯燥, 但很重要, 了解它们才能继续研究更深层的问题。编程
分布式系统中的网络模型
同步网络(synchronous network)
这里的同步网络和编程中的同步阻塞io和异步非阻塞io是两回事, 不要弄混了。网络
同步网络是指:
i). 全部节点的时钟漂移有上限
ii). 网络的传输时间有上限
iii). 全部节点的计算速度同样.架构
这意味着整个网络按照round运行, 每一个round中任何节点都要执行完本地计算而且能够完成一个任意大小消息的传输. 一个发出的消息若是在一个round内没有到达, 那么必定是网络中断形成的, 这个消息会丢失, 不会延迟到第二个round到达. 在现实生活中这种网络比较少, 尽管不多, 同步网络仍然是在计算机科学中是不可缺乏的一个模型, 在这种模型下能够解决一些问题, 好比拜占庭式故障. 但咱们天天打交道的网络大多都是异步网络.异步
异步网络(asynchornous network)
和同步网络相反, 节点的时钟漂移无上限, 消息的传输延迟无上限, 节点计算的速度不可预料. 这就是和咱们天天打交道的网络类型. 在异步网络中, 有些故障很是难解决, 好比当你发给一个节点一个消息以后几秒钟都没有收到他的应答, 有可能这个节点计算很是慢, 可是也多是节点crash或者网络延迟形成的, 你很难判断究竟是发生了什么样的故障.async
Fault, Error and Failure
这不是绕口令, 你必定要区分他们的关系. 过去不少时候这些词汇混用致使不少问题, 后来统一了这几个词的定义:分布式
Fault: 在系统中某一个步骤偏离正确的执行叫作一个fault, 好比内存写入错误, 可是若是内存是ECC的那么这个fault能够马上被修复, 就不会致使error.post
Error: 若是一个fault没能在结果影响到整个系统状态以前被修复, 结果致使系统的状态错误, 那么这就是一个error, 好比不带ECC的内存致使一个计算结果错误.设计
Failure: 若是一个系统的error没能在错误状态传递给其它节点以前被修复, 换句话说error被扩散出去了, 这就是一个failure.orm
因此他们的关系是fault致使error, error致使failure. 在分布式系统中, 每一个节点很难肯定其它节点内部的状态, 一般只能经过和其余节点的交互监测到failure. 接下来咱们所说的故障通常都是指failure.
分布式系统中的故障模型
在分布式系统中, 故障可能发生在节点或者通讯链路上, 下面咱们按照从最普遍最难的到最特定最简单的顺序列出故障类型:
byzantine failures: 这是最难处理的状况, 一个节点压根就不按照程序逻辑执行, 对它的调用会返回给你随意或者混乱的结果. 要解决拜占庭式故障须要有同步网络, 而且故障节点必须小于1/3, 一般只有某些特定领域才会考虑这种状况经过高冗余来消除故障. 关于拜占庭式故障你如今只要知道这是最难的状况, 稍后咱们会更详细的介绍它.
crash-recovery failures: 它比byzantine类故障加了一个限制, 那就是节点老是按照程序逻辑执行, 结果是正确的. 可是不保证消息返回的时间. 缘由多是crash后重启了, 网络中断了, 异步网络中的高延迟. 对于crash的状况还要分健忘(amnesia)和非健忘的两种状况. 对于健忘的状况, 是指这个crash的节点重启后没有完整的保存crash以前的状态信息, 非健忘是指这个节点crash以前能把状态完整的保存在持久存储上, 启动以后能够再次按照之前的状态继续执行和通讯.
omission failures: 比crash-recovery多了一个限制, 就是必定要非健忘. 有些算法要求必须是非健忘的. 好比最基本版本的Paxos要求节点必须把ballot number记录到持久存储中, 一旦crash, 修复以后必须继续记住以前的ballot number.
crash-stop failures: 也叫作crash failure或者fail-stop failures, 它比omission failure多了一个故障发生后要中止响应的要求. 好比一个节点出现故障后当即中止接受和发送全部消息, 或者网络发生了故障没法进行任何通讯, 而且这些故障不会恢复. 简单讲, 一旦发生故障, 这个节点 就不会再和其它节点有任何交互. 就像他的名字描述的那样, crash and stop.
分布式系统中的故障类型还有其余的分类方法, 有些分类会把omission去掉, 有些会加入performance failures, 有些会把crash-stop和fail-stop根据故障检测能力区分开, 此处介绍的是使用较为普遍的一种分类方法. 它们的关系以下:
这四种故障中, 拜占庭式故障是很是难以解决的, Leslie Lamport证实在同步网络下, 有办法验证消息真伪, 故障节点不超过1/3的状况下才有可能解决. 在现实中, 这类问题解决成本很是高, 只有在很是关键的领域会考虑使用BFT(Byzantine Fault Tolerance)的设计. 好比NASA的航天飞机有5台能够抵抗各类射线影响的AP-101系列计算机, 其中四台使用一样的软件运行, 另一台独立运行另一个独立编写版本的软件. 空客A320有7台计算机, 分别是三种硬件上运行的三套独立编写的软件. 美国海军的海狼级核动力攻击型潜水艇(SSN-21)也采用了多组计算机控制. 绝大多数应用是不太考虑重力加速度和射线辐射对硬件的影响的, 稍后本文会介绍拜占庭将军问题来具体解释一下这类问题. 大多数分布式应用主要是关注crash-recovery的状况, 而crash-stop是一种过于理想化的状况, 后面咱们在介绍Paxos算法的时候会给你们讲解为何这个过于理想化的故障模型会带来什么样的问题.
Consensus问题
之因此要介绍Consensus问题是由于Consensus问题是分布式系统中最基础最重要的问题之一, 也是应用最为普遍的问题, 他比其余的分布式系统的经典问题好比self-stabilization的实际应用要多, 咱们能够经过介绍Consensus问题来更加深刻得介绍一下以前提到的Linearizability和Sequential Consistency.
Consensus所解决的最重要的典型应用是容错处理(fault tolerannce). 好比在原子广播(Atomic Broadcast)和状态机复制(State Machine Replication)的时候, 咱们都要在某一个步骤中让一个系统中全部的节点对一个值达成一致, 这些均可以概括为Consensus问题. 可是若是系统中存在故障, 咱们要忽略掉这些故障节点的噪音让整个系统继续正确运行, 这就是fault tolerance. Consensus问题的难点就在于在异步网络中如何处理容错.
Consensus问题的定义包含了三个方面, 通常的Consensus问题定义为:
termination: 全部进程最终会在有限步数中结束并选取一个值, 算法不会无尽执行下去.
agreement: 全部非故障进程必须赞成同一个值.
validity: 最终达成一致的值必须是V1到Vn其中一个, 若是全部初始值都是vx, 那么最终结果也必须是vx.
Consensus要知足如下三个方面: termination, agreement 和 validity. 这三个要素定义了全部Consensus问题的本质. 其中termination是liveness的保证, agreement和validity是safety的保证, 分布式系统的算法
liveness和safety就像一对死对头, 关于liveness和safety的关系, 咱们将会在本系列后面的文章中介绍. 全部须要知足这三要素的问题均可以看作是Consensus问题的变体.
在异步网络中, 若是是拜占庭式故障, 那么Paxos和Raft也没法解决这一类问题, 严格讲这是没有办法解决的, 很长一段时间内咱们只看到在航天和军事领域经过同步网络解决此类问题. (直到Babara Liskov在2002年提出PBFT咱们才能够在放松liveness的状况下解决此类问题, 为此Barbara Liskov得到了图灵奖. 咱们可能会在未来的文章中介绍PBFT). 对于通常的应用来讲拜占庭故障出现的几率过低而解决的成本实在是过高, 因此咱们通常不考虑拜占庭式故障. 咱们主要是关注crash-recovery failure的模型下的异步网络. 这种状况下根据FLP理论, 只要有一个故障节点, Paxos/Raft都是有可能进入无限循环而没法结束的, 可是实际上这个几率很是低, 若是放松liveness的要求, 咱们认为这种状况下Paxos/Raft是能够解决的. 如下介绍Consensus问题的时候咱们都不考虑拜占庭式故障, 咱们的故障模型是crash-recovery failures, 网络模型是异步网络.
在同步网络中由于全部节点时间偏移有上限, 全部包的传输延迟也有上限, 节点会在一个round内完成计算而且传输完成, 因此一旦超过必定时间尚未收到返回的消息, 咱们就能够肯定要么网络中断要么节点已经crash. 可是咱们现实当中都是异步网络, 传输延迟是没有固定上限的, 当很长时间一个节点都没有返回消息的时候, 咱们不知道是这个节点计算速度太慢, 仍是已经crash了. 若是是这个节点计算太慢, 超时以后, 过了一会这个节点又把结果再发回来了, 这就超出crash-stop故障模型的范围了, 这种状况须要用crash recovery的模型来解决. 在异步网络中没法区分crash和包延迟会致使consensus问题很是难解决。
今天是分布式系统发展史第二篇的第一部份内容,明天咱们将继续发布第二部份内容《两阶段提交和三阶段提交的发展史》,敬请期待。
若是您想投稿给咱们,或者想转发和采用咱们的稿件,请回复“合做”,小编会在2小时内回复您的投稿和合做需求。
本文做者:Daniel,吴强, 现任点融网首席社交平台架构师,前盛大架构师, 专一分布式系统和移动应用, 有十三年的开发经验, 目前在点融作最爱的两件事情: 写代码和重构代码。
随着新一轮融资,点融网开始了大规模的扩张,须要各类优秀人才的加入,若是您以为本身够优秀,欢迎加入咱们!