vlambda博客
学习文章列表

分布式理论基础CAP和BASE理论

介绍

对于集中式的事务处理系统,我们可以使用很成熟的ACID模型来保证数据的强一致性。而对于分布式系统,如果我们期望实现一个满足ACID特性的分布式事务,很可能就会在系统的可用性和强一致性之间出现冲突,于是,在如何构建一个兼顾可用性和一致性的分布式系统课题下,衍生出了如CAP和BASE这样的分布式系统经典理论。


一、CAP理论

CAP理论在2000年7月份被首次提出,CAP理论告诉我们,一个分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容错性(P:Partition tolerance)这三个基本需求,最多只能同时满足其中的两项。


C:Consistency,强一致性

一致性是指在分布式环境中多个数据副本保持一致。在分布式系统中,如果对一个数据的更新操作成功后,所有的用户都可以读取到最新的值,那么这样的系统就具有强一致性。


A:Availability,高可用性

系统提供的服务必须一直处于可用,对于用户的每一个请求总是能在有限时间内返回结果。


P:Partition Tolerance,分区容错性

分布式系统在遇到任何网络分区故障时,仍然需要能够保证对外提供满足一致性和可用性的服务。


网络分区是指在分布式系统中,不同的节点分布在不同的子网络(机房或异地网络等)中,由于一些特殊的原因导致这些子网络之间出现网络不连通的情况,但各个子网络内部网络是正常的,从而导致整个系统的网络环境被切分成了若干个孤立的区域。组成一个分布式系统的每个节点的加入与退出都可以看作是一个特殊的网络分区。


既然一个分布式系统不能同时满足C、A、P三个需求,那么如何抉择呢?

放弃P

最简单的极端做法,就是放置在一个节点上,也就只有一个个数据副本,所有读写操作就集中在一台服务器上,有单点故障问题。放弃P也就意味着放弃了系统的可扩展性,所以分布式系统一般来说,都会保证P。


放弃A

一旦系统遇到网络分区或者其他故障时,服务需要等待一段时间,在等待时间内就无法正常对外提供服务,即服务不可用。


放弃C

事实上,放弃一致性是指放弃数据的强一致性,无法保证数据保持实时的一致性,而保留最终一致性,具体多久达到数据同步取决于存储系统的设计,主要包括数据副本在不同节点之间的复制时间长短。

CAP只能3选2,因为在分布式系统中,容错性P肯定是必须有的,所以这时候无非就两种情况,网络问题导致要么错误返回,要么阻塞等待,前者牺牲了一致性,后者牺牲了可用性。


分区容错性往往是分布式系统必然要面对和解决的问题,所以我们应该把精力放在如何根据业务特点在A和C之间寻求平衡。对于单机软件,因为不用考虑P,所以肯定是CA型,比如MySQL。其实对于单机软件来说,也不用CAP,因为CAP理论适用于分布式系统,不适用单机系统。对于分布式软件,因为一定会考虑P,所以又不能兼顾A和C的情况下,只能在A和C做权衡,比如HBase,Redis等,做到服务基本可用,并且数据最终一致即可。


基于此,所以就产生了BASE理论。



二、BASE理论

多数情况下,其实我们也并非一定要求强一致性,部分业务可以容忍一定程度的延迟一致,所以为了兼顾效率,发展出来了最终一致性理论 BASE。


BASE理论是Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性)三个短语的缩写。


核心思想是:即使无法做到强一致性,但每个应用都可 以根据自身业务特点,采用适当的方式来使系统达到最终一致性。


一句话概括,做事别走极端,BASE 是对 CAP 理论中的 C 和 A 进行权衡得到的结果。不是强一致,而是最终一致,不是高可用,而是基本可用。


Basically Available(基本可用)

基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。响应时间的损失:出现故障或者高峰,查询结果可适当延长,以用户体验上限为主。功能上的损失:例如淘宝双11,为保护系统稳定性,正常下单,其他边缘服务可暂时不可用。


Soft State(软状态)

软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。通俗的讲:允许存在不同节点同步数据时出现延迟,且出现数据同步延迟时存在的中间状态也不会影响系统的整体性能。


Eventually Consistent(最终一致)

最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况,要求最终达到一致,而不是实时强一致。数据到达一致性的时间取决于网络延迟、系统负载和数据复制方案设计等因素。


在实际工程中,最终一致性存在以下5种主要变种:

因果一致性(Causal consistency)

因果一致性是指进程A在更新完某个数据后通知了进程B,那么进程B之后对该数据的访问都应该能够获取到进程A更新后的最新值,如果进程B要对该数据进行更新操作的话,务必基于进程A更新后的最新值,即不能发生丢失更新的情况。同时,与进程A无因果关系的进程C的数据访问则没有这样的限制。


读己之所写(Read your writes)


解决方案:

  • 一种方案是对于一些特定的内容我们每次都去主库读取。(问题主库压力大)

  • 我们设置一个更新时间窗口,在刚更新的一段时间内,我们默认都从主库读取,过了这个窗口之后,我们会挑选最近更新的从库进行读取

  • 我们直接记录用户更新的时间戳,在请求的时候把这个时间戳带上,凡是最后更新时间小于这个时间戳的从库都不予以响应


会话一致性(Session consistency)

会话一致性是指在同一个有效的会话中是实现读己之所写的一致性,也就是说,执行更新操作后,客户端能够在同一个会话中始终读取到该数据的最新值。


单调读一致性(Monotonic read consistency)

单调读一致性是指一个进程从系统中读取出一个数据值后,那么系统对于该进程后续的任何数据访问都不应该返回更旧的值。多次刷新返回旧数据出现灵异事件。解决方案:通过hash映射到同一台机器。


单调写一致性(Monotonic write consistency)

单调写一致性是指一个系统需要能够保证来自同一个进程的写操作被顺序地执行。


实际上,最终一致性并不是只有那些大型分布式系统才会涉及的特性,许多关系型数据库都采用了最终一致性模型。关系型数据中,大多都会采用同步和异步的方式来实现主备数据复制。


同步方式中,数据的复制过程通常是更新事务的一部分,因此,在事务完成后,主备数据库的数据就会达到一致。而在异步方式中,备库的更新往往会存在延时,这取决于事务日志在主备数据库之间传输的时间长短,但是最终会保证主备数据的一致性。


在实际的分布式场景中,不同业务单元和组件对数据一致性的要求是不同的,因此,在具体的分布式系统架构设计过程中,ACID特性与BASE理论往往又会结合在一起使用。


推荐阅读



看完本文有收获?请转发分享给更多人

关注「并发编程之美」,一起交流Java学习心得