分布式系统中,保证集群中所有节点中的数据完全相同并能够对某个提案(Proposal)达成一致,核心过程往往需要通过共识算法来达成分布式一致性。
区块链系统是一个分布式系统,对于分布式多节点结构,首要问题就是保证一致性。
CAP理论
区块链作为分布式系统,因此也符合分布式计算领域公认的定理:CAP理论。
- CAP理论基本概念
CAP定理指出,一个分布式计算系统,不可能同时满足以下三点:
1.一致性(Consistency):更新操作成功并返回客户端完成后,分布式的所有节点在同一时间的数据完全一致。任何操作应该都是原子的,发生在后面的事件能看到前面事件发生导致的结果,注意这里指的是强一致性。
2.可用性(Availability):在有限时间内,任何非失败节点都能应答请求,但是不能保证获取到的数据时最新的。
3.分区容错性(Partition tolerance):网络可能发生分区,即节点之间的通信不可保障。分布式系统即使在部分节点故障或者分区故障的情况下,依然能够对外提供服务(进行容错处理)。- CA without P(弱化分区容错性)
如果要保证C(强一致性)和A(可用性),则无法保证分区容错性。但是分布式系统是无法避免分区的,两阶段的提交算法(如ZooKeeper等)主要考虑了这种设计。 - CP without A(弱化可用性)
弱化A(可用性),那么每个请求都需要在server之间保持强一致性,而分区的出现会导致节点之间数据同步时间延长,但是CP是可以保证的。例如对一致性比较敏感的应用,例如ATM机、电子支付等,当系统出现故障时,直接拒绝服务。 - AP without C(弱化一致性)
要求高可用性并允许分区容错,则需要弱化一致性。因为一旦一个节点或分区发生故障失去联系,为了保证高可用性,每个节点只能使用本地数据库提供服务,但这样会导致各个节点的数据不一致。这种情况一般是对一致性不敏感的应用,可以允许在新版本上线后过一段时间才最终更新完成,期间不保证一致。例如NoSQL、DNS、web缓存都属于此类。
- CA without P(弱化分区容错性)
PoW共识机制为AP模式,牺牲强一致性,确保高可用性和分区容错性,从而达到最终一致性。
如果区块链要满足一致性C(强一致性),即所有节点的操作的执行顺序都完全相同,一个节点提交更新操作需同时反映在其他节点。在异步网络中,想要满足CP模式,则需要建立一个中心节点存储所有数据,其他节点与之相连,则更新和获取数据的操作均从中心节点获取,但这与区块链的去中心化相违背,因此区块链不能满足CAP理论的C。
FLP不可能原理
在网络可靠,存在节点失效(即便是一个)的最小化异步模型系统中,不存在一个可以解决一致性问题的确定性算法。
因此,不存在一个在异步分布式系统中任何情况下都能达成一致共识的共识算法。
一致性模型
- 定义
分布式系统中各节点,执行一些列操作后,在约定协议下,对外呈现的状态是一致的。即保证集群中所有节点中的数据完全相同并且能够对某个提案(Proposal)达成一致。
一致性不代表结果正确与否,而是系统对外呈现的状态一致与否。所有节点都达成失败状态也是一种一致。
分布式事务一致性
事务是数据库管理系统执行过程中的一个逻辑单元,由一个有限的数据库操作序列构成。
确保操作序列在多个服务节点中执行的顺序是一致的。
分布式数据一致性
数据在多份副本中存储时,各副本中的数据是一致的。
因此,保证分布式事务一致性,也就保证了数据的一致性。
- 一致性要求
1.有限性:达成一致的结果在有限时间内完成。
2.约同性:不同节点最终完成决策的结果是相同。
3.合法性:决策的结果必须是某个节点提出的方案。
在分布式系统中,如果一个由节点提出的提案,能够在有限时间内使得所有节点达成一致的结果,那么该提案达到了一致性。
- 分类
按照一致性要求的不同,可以分为四大类:严格一致性、强一致性、弱一致性以及最终一致性。
1.严格一致性(strict consistency)
对于数据项
X
的任何读操作将返回最近一次对X
进行的写操作所对应的值。
严格一致性的问题在于其依赖于绝对的全局时间。对于进程来说,所有写操作都是瞬间可见的,系统维持着一个绝对的全局时间。如果一个数据项被改变,在数据项改变之后,任何节点的任何进程随时执行读操作,所有在该数据项上执行的后续读操作都将得到新数值。
严格一致性是在系统不发生任何故障且所有节点之间的通信无需任何时间这种理想的条件下,才能达到。此时,整个分布式系统其实就等价于一台机器。现实中是不可能达成的。
2.强一致性(strict consistency)
当分布式系统更新操作完成后,任何多个进程或线程访问系统都会获得最新值。
顺序一致性(sequential consistency)
任何执行结果都相同,所有进程对数据存储的读、写操作是按照某种序列顺序执行,并且每个进程的操作按照程序所指定的顺序出现在这个序列中。
线性一致性(Linearizability)
一种弱于严格一致性但强于顺序一致性的一致性模型是线性一致性。
假设操作具有一个全局有效的时间戳,但是这个时钟仅具有有限的精度。要求时间戳在前的进程先执行。
线性化是根据一系列同步时钟确定序列顺序。
3.弱一致性(weak consistency)
系统并不保证后续进程或线程的访问都会返回最新的更新值。系统在数据成功写入后,不承诺立即可以读到最新写入的值,也不会承诺多久之后可以读取到。但会尽可能保证在某个时间级别(比如秒级别)之后,可以让数据达到一致性状态。
也就是说,如果能容忍后续的部分或者全部访问不到,则是弱一致性。
4.最终一致性(eventual consistency)
弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。
也就是说,如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
DNS是一个典型的最终一致性系统。
最终一致性的变型
- 因果一致性
如果A进程在更新后向B进程通知更新的完成,那么B的访问操作将会返回更新的值。没有因果关系的C进程将会遵循最终一致性的原则。- 读己所写一致性
因果一致性的特定形式。一个进程总可以读到自己更新的数据。- 会话一致性
读己所写一致性的特定形式。进程在访问存储系统同一个会话内,系统保证该进程读己所写。- 单调读一致性
如果一个进程已经读取到一个特定值,那么该进程不会读取到该值以前的任何值。- 单调写一致性
系统保证对同一个进程的写操作串行化。
上述最终一致性的不同方式可以进行组合,e.g. 单调读一致性和读己所写一致性可以组合实现。组合后实现:读取自己更新的数据,和一旦读到最新的版本就不会再读到老版本,对于架构上的程序开发,会少很多麻烦。
- 一致性问题场景
1.节点之间的网络通信是不可靠的,包括消息延迟、乱序和内容错误等;
2.节点的处理时间无法保障,结果可能出现错误,甚至节点自身可能发生宕机。
3.同步调用可以简化设计,但会严重降低分布式系统的可扩展性。
共识性
- 定义
分布式系统中多个节点间,相互对某个状态达成一致结果的过程。
共识性与一致性的区别
一致性往往指分布式系统中多个副本对外呈现的数据的状态。如顺序一致性、线性一致性,描述了多个节点对数据状态的维护能力。
共识性描述了分布式系统中多个节点之间,彼此对某个状态达成一致结果的过程。
一致性描述的是结果状态,共识则是达成一致性的一种手段、过程。达成某种共识并不意味着就保障了一致性(此处指强一致性)。只能说共识机制,能够实现某种程度上的一致性。
共识算法
共识算法解决的是对某个提案(Proposal),大家达成一致意见的过程。提案的含义在分布式系统中十分宽泛,如多个事件发生的顺序、某个键对应的值、谁是领导.....等等,可以认为任何需要达成一致的信息都是一个提案。
实践中,一致性的结果往往还需要客户端的特殊支持,典型地通过访问足够多个服务节点来验证确保获取共识后的结果。
对于分布式系统来说,各个节点通常都是相同的确定性状态机模型(又称为状态机复制问题,state-machine replication),从相同初始状态开始接收相同顺序的指令,则可以保证相同的结果状态。因此,系统中多个节点最关键的是对多个事件的顺序进行共识,即排序。
拜占庭将军问题
在分布式计算上,不同的计算机通过讯息交换,尝试达成共识;但有时,系统上协调计算机(Coordinator / Commander)或 成员计算(Member / Lieutanent)可能因系统错误并交换错的信息,导致影响最终的系统一致性。即,在系统不同的机器之间会传递错误的消息,这种情况即为拜占庭问题,与「网络分割、机器崩溃」是不同的。
一般情况下,失败、出现故障(非响应)情况被称为非拜占庭错误,伪造信息恶意响应的情况被称为拜占庭错误,对应的节点也称为拜占庭节点。
因此拜占庭错误问题讨论的范围更广,它是讨论在允许少数恶意节点的情况下达成一致的问题。
- 非拜占庭容错类算法(Crash Fault Tolerance 「CFT」)
针对常见的非拜占庭错误(普通错误情况),已经存在一些经典的解决算法,包括Paxos、Raft及其变种等。这类容错算法往往性能比较好,处理较快,容忍不超过一半的故障节点。
Raft协议不能容忍拜占庭问题,但是能够在非拜占庭错误情况下,有网络延迟、分区、丢包、冗余和乱序等错误情况出现时,都可以保证其操作的正确性。
- 拜占庭容错类算法(Byzantine Fault Tolerance「BFT」)
对于要能容忍拜占庭的问题,一般包括PBFT(Practical Byzantine Fault Tolerance)为代表的确定性系列算法、PoW为代表的概率算法等。- 对于确定性算法,一旦达成对某个结果的共识就不可逆转,即共识是最终结果。
- 对于概率性算法,共识结果则是零时的,随着时间的推移或某种强化,共识结果被推翻的概率越来越小,成为事实上的最终结果。
拜占庭容错算法往往性能较差,容错不超过1/3的故障节点。
接下来要对非拜占庭问题的一致性算法Paxos和Raft,以及拜占庭问题的一致性算法PoS、PoW和DPoS进行学习。