分布式系统CAP理论深入探索和分析

1.理想的计算机到分布式系统

在处理和分析数据时,最理想的环境是这样的:
一台有无限存储和计算能力的“超级计算机”,可以提供无穷大的容量,并且可以将计算时间降低到无穷小。

寻找解决办法

这样一台“超级计算机”在现实世界中并不存在。计算机的存储和计算能力始终要受到客观物理规律的限制。在可预见的将来,单位存储单元上无法存储超量的数据;而在运行计算任务时,由于芯片计算能力是有限的,当计算需求超过瞬时计算能力时,往往会发生排队现象。为了解决大量数据的存储和计算能力不足的问题,我们有两种选择:
1.纵向扩展
即升级硬件设备。通过如升级存储量更高的硬盘、单位时间运算速度更高的芯片,可以为计算机提升性能和存储量,来解决上述问题。但这种硬件的升级会受到计算机本身架构的局限,同时进一步升级所需要的成本会快速上升,从而使得升级硬件的边际效益快速下降。此外,升级所用的硬件依然具有其自身的局限性,并不能彻底解决上述的问题。

2.横向扩展
使用多台普通计算机来模拟“超级计算机”。也就是使用多台机器各自并行地进行存储和计算这种方式进行模拟。使用这种方式构建的计算机系统叫做分布式系统,它具有以下三个特点:一组计算机、通过网络传递信息、协调计算机的行为。通过这种方式,我们可以近似地获得无限的存储和计算能力,解决单机下存储和计算的局限。

分布式系统作为突破口

作为通过网络连接的多台计算机系统,分布式系统的设计目标一般包括:

扩展性 :增加机器不改变或极少改变系统行为,并能获得近似线性的性能提升;
性能 :指分布式系统进行服务时的延时和吞吐率是满足用户需要的;
可用性 :分布式系统的核心需求,表示分布式系统是否处于整体可服务并且一直可服务的状态;
容错性 :系统发生错误时,系统有对错误进行规避和恢复的能力。

通过搭建合理的系统架构,进行恰当的数据管理,分布式系统是可以满足以上的设计目标的。一套顺畅运行的分布式系统可以在很大程度上满足大量数据的存储和计算需求。尽管如此,任何事情都需要付出代价。分布式的方式不仅增加了工程复杂性,甚至在理论上会出现不可逾越的障碍。本文将对这些优缺点进行必要的探讨。

分布式系统产生新的问题

为了实现分布式系统的设计目标,我们需要先了解分布式系统实现过程中需要克服的问题和困难。一套分布式系统的主要物理要素包括节点的数目以及节点间的距离。仅这两点的更改就会引入以下限制:

节点数增加会导致系统整体出错概率增大
节点数增加会导致节点间通信量增加
节点间距离增加会导致系统最优(或部分)性能变差

抛开工程的视角,仅从理论层面看,分布式系统也存在着如下三类视角的系统划分:

保持一致:系统中相关数据间的逻辑关系应当是正确和完整的。极端情况下,从系统中任意部分读取而获得的数据应当都为最近写入的数据;
处理失效 :分布式系统可能出现的失效状况有三类:节点失效、网络分区失效、拜占庭失效。极端情况下,系统的执行和操作不会受到任何系统内部失效的影响;
时钟同步 :分布式系统有两种模型:同步系统和异步系统。同步系统会确保所有执行过程的步调一致,且各执行过程有精确的时钟。即任意处理过程能够得到精确的执行流程的偏序关系,也就意味着每个处理过程和通信都在有限的时间内进行。异步系统则相反,没有任何时序性保证。即各处理过程是完全以自己的节拍在运行,不存在有效的同步时钟,也意味着过程间的通信延时可能会趋于无穷大。

针对物理层面和理论层面存在的种种问题,分布式系统研究人员希望找到这些问题的答案:是否可以通过硬件技术和软件算法来克服困难,实现一个理想的或接近理想的分布式系统,以达成模拟那台“超级计算机”的设计目标?

理想环境的困境

不幸的是,在实际应用中,理想的分布式系统实际是不可能实现的。
在这里插入图片描述
图为历史上最著名的第一类永动机“魔轮”。人类花费超过500年的时间才学习到:Something is impossible.
P.S. “中华宇宙能源超磁能机车”——即使在永动机历史上也是非常“出彩”的。可以去百度永动机贴吧长长见识 (╯□╰)

为什么?我们可以从一致性问题(Consensus Problem)——也就是分布式系统必须解决的一个问题出发,同时考虑其他设计目标,看看可以推导得到什么样的结果。一致性问题(Consensus Problem)是指:

一致(Agreement) :每个正确的执行过程应该在相同的值上达成一致;
完整(Integrity) :每个正确的执行过程最多只能决定一个值。如果它决定了某个值的话,这个值一定是被某个执行过程提出的;
终止(Termination) :所有的执行过程最终会做出一个决定;
正确(Validity) :如果所有正确的执行过程提出了相同的值V,那么所有正确的执行过程都会决定值V。

基于以上要求,可以推导出在分布式系统领域非常重要的定理:

FLP不可能性
在假设网络可靠、计算节点只会因崩溃而失效的最小化异步模型系统中,仍然不存在一个可以解决一致性问题的确定性算法。

仅这一条定理就已经打碎了我们模拟“超级计算机”的幻想。不过从务实的角度考虑,虽然不能实现理想的分布式系统,但我们是否可以通过对系统主要设计指标进行一定的妥协,来设计出一个理论上可行的、可以满足实际需求的分布式系统呢?

权衡后的转机

幸运的是,由Eric Brewer等人提出的 CAP定理 已经为我们回答了这个问题。 CAP定理 的一个表述是:

CAP定理
分布式计算系统不可能同时确保一致性、可用性和分区容忍性。
一致性(Consistency) :所有节点在同一时刻能够看到同样的数据,也即“强一致性”; 
可用性(Availability) :确保每个请求都可以收到确定其是否成功的响应; 
分区容忍性(Partition tolerance) :因为网络故障导致的系统分区不影响系统正常运行。

这也就意味着,我们虽然不能使某个分布式场景同时满足三个性质,但可以使之同时满足三个中的两个。更进一步说,对于包含多个分布式场景的分布式系统,我们甚至可以在三个性质的程度上进行适当的权衡。
CAP权衡方案
CAP权衡方案
我们把解决一致性问题(Consensus Problem)的算法叫做一致性算法(Consensus Algorithm)或者一致性协议(Consensus Protocol)。CAP定理能够将这些一致性算法的集合进行归类:

C+A :以2阶段提交(2 phase commit)为代表的严格选举协议。当通信中断时算法不具有终止性(即不具备分区容忍性);
C+P :以Paxos、Raft为代表的多数派选举算法。当不可用的执行过程超过半数时,算法无法得到正确结果(即会出现不可用的情况);
A+P :以Gossip协议为代表的冲突解决协议。当网络分区存在和执行过程正确时,只能等待分区消失才保持一致性(即不具备强一致性)

基于CAP定理,我们需要根据不同场景的不同业务要求来进行算法上的权衡。对于分布式存储系统来说,网络连接故障是无法避免的。在设计系统时不得不考虑分区容忍性,所以我们实际上只能在一致性和可用性之间进行权衡。

强一致性与可用性的矛盾会导致十分令人头疼的抉择。在实际情况中,对于不是那么重要的数据的存取操作,往往会调低一致性来增加可用性。如GeneDock的账户信息管理数据,是以最终一致性的方案分发到各个业务域的,这样既满足了各域业务API的性能需求,又使得跨域的账户信息同步功能得以实现。当然,对于敏感的元数据信息,GeneDock采取的则是强一致性的方案。

在这里插入图片描述
知名分布式系统的主场景设计权衡

特别值得一提的经典设计范例是阿里巴巴的OceanBase系统。它将数据分为了冷数据和热数据两个不同的场景。对于冷数据,规定只读不写。这样就不需要处理分布式写操作带来的一致性问题,只需保证可用性和分区容忍性即可(即AP场景)。而对于新增的热数据,由于用户需要频繁访问,所以采取不同的服务器分片进行服务,本地读写的模式,不需要考虑网络分区的问题(即CA场景)。通过对CAP定理的深刻理解和灵活运用,构建出了满足高并发读写、处理海量金融数据的分布式数据库。

分布式系统总结

在计算的世界里,一切都是有代价的。 我们必须根据业务实际场景,在关键的业务指标中进行权衡,进而决定合适的解决方案。必须承认,很多系统声称能够解决的问题其实已经被理论证明是不可实现的,这也客观上要求用户在选择云服务提供商的时候一定要擦亮眼睛,不能被过度的宣传所误导。

GeneDock的分布式系统解决方案是在深入考量了生物信息分析领域的实际需求,对许多问题做了艰难权衡之后才确定下来的,已经经受住了近两年的大规模商业计算和存储业务的考验。无论是在针对计算量巨大的全基因组分析或BLAST等分析任务,还是在大规模基因数据的存取及传输场景中,GeneDock对解决方案都进行了精心的设计和实现,确保任务运行的稳定性、数据存储的可靠性和数据传输的正确性,同时使整体系统运行结果准确一致。

参考资料
转自:https://www.cnblogs.com/firstdream/p/6585923.html
一致性问题:https://en.wikipedia.org/wiki/Consensus_(computer_science)
FLP不可能性:http://cs-www.cs.yale.edu/homes/arvind/cs425/doc/fischer.pdf
CAP定理:https://en.wikipedia.org/wiki/CAP_theorem

2.分布式算法

1.Paxos

Paxos目标:
支持分区容忍性和强一致性,分区容忍性比较简单,主要在实现线性一致性,那么需要一个leader,理论上找一台一直当leader就ok了,但是高可用也需要兼顾,保证大部分情况下高可用,那么需要在机器崩溃的情况下快速选举leader。
客户端访问流程:
正常情况:客户端访问任何一台机器创建节点,如果是leader,那么直接向自己维护的follower节点写入数据,如果半数以上节点返回成功,那么返回客户端写入成功。如果客户端访问的是follow节点,那么follow节点会找到leader节点处理以上过程,然后返回客户端。采用消息广播模式
在这里插入图片描述
崩溃恢复
如果leader服务器发生崩溃,则zab协议要求zookeeper集群进行崩溃恢复和leader服务器选举。
ZAB协议崩溃恢复要求满足如下2个要求:
3.1. 确保已经被leader提交的proposal必须最终被所有的follower服务器提交。
3.2. 确保丢弃已经被leader出的但是没有被提交的proposal。
在这里插入图片描述
数据同步
1.在zookeeper集群中新的leader选举成功之后,leader会将自身的提交的最大proposal的事物ZXID发送给其他的follower节点。follower节点会根据leader的消息进行回退或者是数据同步操作。最终目的要保证集群中所有节点的数据副本保持一致。
数据同步完之后,zookeeper集群如何保证新选举的leader分配的ZXID是全局唯一呢?这个就要从ZXID的设计谈起。
2. ZXID是一个长度64位的数字,其中低32位是按照数字递增,即每次客户端发起一个proposal,低32位的数字简单加1。高32位是leader周期的epoch编号,至于这个编号如何产生(我也没有搞明白),每当选举出一个新的leader时,新的leader就从本地事物日志中取出ZXID,然后解析出高32位的epoch编号,进行加1,再将低32位的全部设置为0。这样就保证了每次新选举的leader后,保证了ZXID的唯一性而且是保证递增的。

2.Raft

raft 集群中的每个节点都可以根据集群运行的情况在三种状态间切换:follower, candidate 与 leader。leader 向 follower 同步日志,follower 只从 leader 处获取日志。在节点初始启动时,节点的 raft 状态机将处于 follower 状态并被设定一个 election timeout,如果在这一时间周期内没有收到来自 leader 的 heartbeat,节点将发起选举:节点在将自己的状态切换为 candidate 之后,向集群中其它 follower 节点发送请求,询问其是否选举自己成为 leader。当收到来自集群中过半数节点的接受投票后,节点即成为 leader,开始接收保存 client 的数据并向其它的 follower 节点同步日志。leader 节点依靠定时向 follower 发送 heartbeat 来保持其地位。任何时候如果其它 follower 在 election timeout 期间都没有收到来自 leader 的 heartbeat,同样会将自己的状态切换为 candidate 并发起选举。每成功选举一次,新 leader 的步进数都会比之前 leader 的步进数大1。

Raft一致性算法处理日志复制以保证强一致性。

follower 节点不可用
follower 节点不可用的情况相对容易解决。因为集群中的日志内容始终是从 leader 节点同步的,只要这一节点再次加入集群时重新从 leader 节点处复制日志即可。

leader 不可用
一般情况下,leader 节点定时发送 heartbeat 到 follower 节点。
在这里插入图片描述
由于某些异常导致 leader 不再发送 heartbeat ,或 follower 无法收到 heartbeat 。
在这里插入图片描述
当某一 follower 发生 election timeout 时,其状态变更为 candidate,并向其他 follower 发起投票。
在这里插入图片描述
当超过半数的 follower 接受投票后,这一节点将成为新的 leader,leader 的步进数加1并开始向 follower 同步日志。
在这里插入图片描述
当一段时间之后,如果之前的 leader 再次加入集群,则两个 leader 比较彼此的步进数,步进数低的 leader 将切换自己的状态为 follower。
在这里插入图片描述
较早前 leader 中不一致的日志将被清除,并与现有 leader 中的日志保持一致。
在这里插入图片描述

3.Gossip

在所有的Agent之间(包括服务器模式和普通模式)运行着Gossip协议。服务器节点和普通Agent都会加入这个Gossip集群,收发Gossip消息。每隔一段时间,每个节点都会随机选择几个节点发送Gossip消息,其他节点会再次随机选择其他几个节点接力发送消息。这样一段时间过后,整个集群都能收到这条消息。示意图如下。
在这里插入图片描述

4. Two phase commit

两阶段提交协议(two phase commit protocol,2PC)可以保证数据的强一致性,许多分布式关系型数据管理系统采用此协议来完成分布式事务。它是协调所有分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。同时也是解决一致性问题的一致性算法。该算法能够解决很多的临时性系统故障(包括进程、网络节点、通信等故障),被广泛地使用。但是,它并不能够通过配置来解决所有的故障,在某些情况下它还需要人为的参与才能解决问题。参与者为了能够从故障中恢复,它们都使用日志来记录协议的状态,虽然使用日志降低了性能但是节点能够从故障中恢复。

3.常用分布式系统CAP分析

Zookeeper

zookeeper使用zab协议,和paxos算法类似,cap理论实现一致性分区容忍性,但是对高可用性强调每一个节点都能使用,显然zk需要半数以上节点。但是可以通过异地多活来实现高可用。

ETCD

ETCD 使用的是raft协议,和paxos协议类似,但是比paxos协议简单,cap理论实现一致性分区容忍性,但是对高可用性强调每一个节点都能使用,显然zk需要半数以上节点。但是可以通过异地多活来实现高可用。

MongoDB

MongoDB r3.2.0以前选举协议是基于Bully算法,从r3.2.0开始默认使用基于Raft算法的选举策略。

ElasticSearch

elasticSearch使用的是gossip协议,cap理论实现高可用分区容忍性,牺牲强一致性,用最终一致性替代。

Cassandra

cassandra使用的是gossip协议,cap理论实现高可用分区容忍性,牺牲强一致性,用最终一致性替代。

Jumper

一号店的分布式消息系统,jumper使用的是二段提交,cap理论实现强一致性高可用、牺牲分区容忍性,这里使用mongodb数据库带来分区容忍性。

Eureka

Eureka 是 Netflix 出品的用于实现服务注册和发现的工具。 Spring Cloud 集成了 Eureka,并提供了开箱即用的支持。cap理论实现高可用分区容忍性,牺牲强一致性,用最终一致性替代。

参考:
1.[zab协议]https://blog.csdn.net/xiaocai9999/article/details/80641404
2.[raft协议]https://www.backendcloud.cn/2017/11/12/raft-gossip/
3.[Two phase commit]https://www.cnblogs.com/sunddenly/articles/4072882.html

4.反过头来理解CAP理论

在一个shared-data的系统中,我们不可能同时获得以下3个特性:

  • C:一致性,其实这里的一致性,是指线性一致性。
  • A:可用性,是指系统中每一个non-failing的节点都可以在一个合理的时间里成功的完成读写操作。
  • P:容忍网络分区。

下面对CAP定理做几点说明。

  • 1.因为CAP定理在描述的是一个shared-data的系统,网络分区是必然存在的,系统必须处理网络分区的情况。
  • 2.定理中的一致性和可用性都是非常苛刻的条件。线性一致性是非常强的一致性模型,除了线性一致性模型,还有很多比线性一致性弱很多的一致性模型,如果你的系统采用了这样的相对较弱一致性模型,其实已经不是CAP定理的范畴了。你是可以实现出一个具有更弱的一致性模型并且同时满足A和P的系统出来。
    (关于什么是线性一致性及其作用可以参考<线性一致性(Linearizability)是并发控制的基础>)
  • 3.同理,A也是非常苛刻的,他强调了每一个节点都可以完成读写操作。所以Paxos虽然是线性一致性的,但是没满足这么苛刻的A的条件。所以也不适用CAP定理。

其实,CAP只是描述了你不可能实现出一种同时具有完美一致性和完美可用性的shared-data系统出来。这个定理基本上没有太多实用性的。目前已经有很多系统,实现了很好的一致性并且具有很好可用性。我们不能说这些现实的系统违反了CAP定理,而是CAP定理不适用于这些现实的系统。Paxos、Zookeeper、etcd就是这样的一个例子。另外,作为对立面的一个例子,Cassandra具有很好的可用性,并且也具有比线性一致性弱一些的一致性。

参考:
1.[Paxos没有违反CAP理论]https://www.jianshu.com/p/770880e5e200

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值