区块链基本原理

FLP不可能原理

FLP 不可能原理:在网络可靠、但允许节点失效(即便只有一个)的最小化异步模型系统中,不存在一个可以解决一致性问题的确定性共识算法(No completely asynchronous consensus protocol can tolerate even a single unannounced process death)。
提出并证明该定理的论文《Impossibility of Distributed Consensus with One Faulty Process》是由 Fischer、Lynch 和 Patterson 三位科学家于 1985 年发表,该论文后来获得了 Dijkstra(就是发明最短路径算法的那位计算机科学家)奖。

FLP 不可能原理告诉我们,不要浪费时间去试图为异步分布式系统设计面向任意场景的共识算法。

FLP 不可能原理在论文中以图论的形式进行了严格证明。要理解其基本原理并不复杂,一个不严谨的例子如下。

三个人在不同房间进行投票(投票结果是 0 或者 1),彼此可以通过电话进行沟通,但经常有人会时不时睡着。比如某个时候,A 投票 0,B 投票 1,C 收到了两人的投票,然后 C 睡着了。此时,A 和 B 将永远无法在有限时间内获知最终的结果,因为他们无法判断究竟是 C 没有应答还是应答的时间过长。如果可以重新投票,则类似情形可以在每次取得结果前发生,这将导致共识过程永远无法完成。

FLP 不可能原理实际上说明对于允许节点失效情况下,纯粹异步系统无法确保共识在有限时间内完成。即便对于非拜占庭错误的前提下,包括 Paxos、Raft 等算法也都存在无法达成共识的极端情况,只是在工程实践中这种情况出现的概率很小。

CAP理论

CAP理论是指一个分布式系统不能同时满足一致性、可用性和分区容错性。

一个分布式系统里面, 节点组成的网络本来应该是连通的. 然而可能因为一些故障, 使得有些节点之间不连通了, 整个网络就分成了几块区域. 数据就散布在了这些不连通的区域中. 这就叫分区.
当你一个数据项只在一个节点中保存, 那么分区出现后, 和这个节点不连通的部分就访问不到这个数据了. 这时分区就是无法容忍的.
提高分区容忍性的办法就是一个数据项复制到多个节点上, 那么出现分区之后, 这一数据项就可能分布到各个区里. 容忍性就提高了.
然而, 要把数据复制到多个节点, 就会带来一致性的问题, 就是多个节点上面的数据可能是不一致的. 要保证一致, 每次写操作就都要等待全部节点写成功, 而这等待又会带来可用性的问题.
总的来说就是, 数据存在的节点越多, 分区容忍性越高, 但要复制更新的数据就越多, 一致性就越难保证. 为了保证一致性, 更新所有节点数据所需要的时间就越长, 可用性就会降低.

分布式系统模型

假设我们有这样一个简单的分布式系统,它包含两个服务G1和G2,这俩服务都保存着同一变量v,其初始值是v0。 G1和G2之间可以互相沟通,同时他们也可以和其他的客户端沟通,如下图所示:
分布式系统
客户端可以读取和修改任意一个服务端的值。当服务端收到请求,他会做相应处理后回复客户端。如果是写请求执行过程如下图所示:
分布式数据写入
如果是读请求,执行过程如下图:
分布式数据读取
现在我们已经建立了一个简单的分布式系统

一致性

Gilbert和Lynch的论文中是这样描述一致性的:

any read operation that begins after a write operation completes must return that value, or the result of a later write operation
在某个写操作完成之后的任何读操作都必须返回该写操作写入的值,或者再之后的写操作写入的值。

在一个一致性的系统中,如果一个客户端写入了某个值到任意一个服务端上,并且得到了服务端的确认,那么客户端再去读的时候,不管是读的哪个服务,都期望拿到写入后的值或者是更新的值。
下图所示是有个不保证一致性的系统:

客户端向G1发送了写请求将v的值从v0变更到v1,然后也得到了G1的写入成功确认,但从G2读到的数据还是旧的数据v0。
下图是一个保证一致性的系统:

在这个系统中,当客户端向G1写入数据v1后,G1也会把数据同步到G2,当G1 G2都完成数据更新后,G1才会告诉客户端写入成功。 之后不过是客户端从G1读还是从G2读,读到的都是最新的值v1。

可用性

Gilbert和Lynch的论文对可用性的描述如下:

every request received by a non-failing node in the system must result in a response 任何一个在线的节点收到的请求必须都做出相应。

在保证可用性的系统中,如果客户端向某个没有宕机的服务端发送了请求,服务端必须响应客户端的请求,不能选择忽略掉客户端的请求。

分区容错性

Gilbert和Lynch的论文对分区容错性的描述如下:

the network will be allowed to lose arbitrarily many messages sent from one node to another 允许网络丢失从一个服务节点到另外一个服务节点的任意信息

这就意味着在我们的分布式系统中,G1发送给G2的信息可能会丢失,如果所有的信息都丢失了,我们的系统可能就会变成这样。

为了保证分区容错性,我们的系统必须在任意个不通的网络分区下正常工作。

证明

现在我们已经了解了什么是一致性、可用性和分区容错性,接下来我们证明下为什么一个分布式系统不能同时满足这三者。
假设存在一个同时满足一致性、可用性和分区容错性的分布式系统。首先我们把这个系统分成两个部分,如下图:

接下来客户端将G1中的v从v0改成v1,因为要满足可用性的要求,G1必须响应客户端的写入请求,但是因为网络的问题,G1没法将数据同步到G2。Gilbert和Lynch将这个阶段称为alpha1阶段,如下图:

再然后,假设有个客户端从G2读了v的值,因为满足可用性要求,G2也必须正常响应,因为网络的问题,G2没有更新到G1的数据,所以G2只能返回v0,Gilbert和Lynch将这个阶段称为alpha2阶段,如下图:

在这里G1返回v1,G2只能返回v1,产生了不一致,和我们的假设相悖,所以证明同时满足一致性、可用性和分区容错性的分布式系统不存在。

BASE理论

CAP理论是严格的数学模型, 其假设网络分区很容易发生, 然而现实中网络分区的情况很少出现或可以通过硬件冗余缓解, 所以通常可以设计出同时满足CA, 尽量满足P的系统.
BASE理论就是设计这样系统的理论.
BASE理论是Basically Available(基本可用),Soft State(软状态)和Eventually Consistent(最终一致性)三个短语的缩写。
其核心思想是:

既是无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

总体来说BASE理论面向的是大型高可用、可扩展的分布式系统。与传统ACID特性相反,不同于ACID的强一致性模型,BASE提出通过牺牲强一致性来获得可用性,并允许数据段时间内的不一致,但是最终达到一致状态。同时,在实际分布式场景中,不同业务对数据的一致性要求不一样。因此在设计中,ACID和BASE理论往往又会结合使用。

基本可用

什么是基本可用呢?假设系统,出现了不可预知的故障,但还是能用,相比较正常的系统而言:

  1. 响应时间上的损失:正常情况下的搜索引擎0.5秒即返回给用户结果,而基本可用的搜索引擎可以在2秒作用返回结果。
  2. 功能上的损失:在一个电商网站上,正常情况下,用户可以顺利完成每一笔订单。但是到了大促期间,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。

软状态

什么是软状态呢?相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种“硬状态”。
软状态指的是:允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。

最终一致性

上面说软状态,然后不可能一直是软状态,必须有个时间期限。在期限过后,应当保证所有副本保持数据一致性,从而达到数据的最终一致性。这个时间期限取决于网络延时、系统负载、数据复制方案设计等等因素。
而在实际工程实践中,最终一致性分为5种:

  1. 因果一致性(Causal consistency): 因果一致性指的是:如果节点A在更新完某个数据后通知了节点B,那么节点B之后对该数据的访问和修改都是基于A更新后的值。于此同时,和节点A无因果关系的节点C的数据访问则没有这样的限制。
  2. 读己之所写(Read your writes): 节点A更新一个数据后,它自身总是能访问到自身更新过的最新值,而不会看到旧值。其实也算一种因果一致性。
  3. 会话一致性(Session consistency): 会话一致性将对系统数据的访问过程框定在了一个会话当中:系统能保证在同一个有效的会话中实现 “读己之所写” 的一致性,也就是说,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。
  4. 单调读一致性(Monotonic read consistency): 单调读一致性指的是:如果一个节点从系统中读取出一个数据项的某个值后,那么系统对于该节点后续的任何数据访问都不应该返回更旧的值。
  5. 单调写一致性(Monotonic write consistency): 单调写一致性指的是:一个系统要能够保证来自同一个节点的写操作被顺序的执行。

在实际的实践中,这5种系统往往会结合使用,以构建一个具有最终一致性的分布式系统。
实际上,不只是分布式系统使用最终一致性,关系型数据库在某个功能上,也是使用最终一致性的。比如备份,数据库的复制过程是需要时间的,这个复制过程中,业务读取到的值就是旧的。当然,最终还是达成了数据一致性。这也算是一个最终一致性的经典案例。

参考资料

  1. CAP理论及其证明
  2. An Illustrated Proof of the CAP Theorem
  3. FLP不可能原理
  4. BASE理论