ACID:数据库的四个特性
CAP:帽子理论
BASE:对应帽子理论的解决思想理论
一,ACID特性
什么是ACID,一般关系型数据库都会保证ACID这个特性,那么ACID对于一致性来说,就是一种最直接且最有效的强一致性。
如果在数据量较小的情况下,可以利用关系型数据库的强一致性解决。
面对具有大规模、高并发的特性,必须采用对高并发压力的”分而治之,大事化小,小事化了”的思想去做,否则难以抗住动辄就是上亿级别流量的需求、以及吞吐量和性能上的需求。
有时候往往我们做不到这样的设计,可能由于业务规则的复杂以及限制,我们无法去将其规划到同一个数据库分片之中,这种情况就需要实现最终一致性了。
何为最终一致性?这就需要我们知道第二个基础理论,CAP(帽子原理)
二,CAP特性
概念: CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
分布式系统的CAP理论:理论首先把分布式系统中的三个特性进行了如下归纳:
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求,也就是尽管网络上有部分消息丢失,但是系统仍然可以继续工作。
系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
CAP原理证明任何分布式系统只可以同时满足两点,无法满足三者兼顾。
三,BASE理论
BASE思想解决了CAP理论所提出的分布式系统的一致性和可用性不可兼得的问题。
BASE是Basically Available(基本可用)
Soft state(软状态)
Eventually consistent(最终一致性)
三个短语的简写,BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。
接下来我们着重对BASE中的三要素进行详细讲解。
BA: 基本可用
S:软状态,这个状态可以在一段时间内不同步,业务可以容忍。
E:最终一致,在一定的时间窗口内,数据达到最终的一致性即可。
我们可以使用数据库的强一致性和BASE理论的弱一致性结合的方式来处理分布式场景中的一些实际问题。
通常分布式服务、分布式事务,在业界中都有那些解决方案:
两阶段提交协议
三阶段提交协议
使用MQ处理分布式业务场景
著名的TCC方案
两阶段提交协议、三阶段提交协议
JEE的XA协议是根据两阶段提交来保证事务的完整性的,并且可以实现分布式服务化的强一致性。
两阶段提交,顾名思义分为两个阶段,一个是准备阶段,一个是提交阶段。准备和提交阶段都是由另外一个事务管理器发起的,
文章地址:http://blog.jobbole.com/95632/
使用MQ处理分布式业务场景
对于RocketMQ 我们都知道他是目前唯一支持分布式事物的消息中间件,他是具体如何实现的呢
文章地址:https://www.jianshu.com/p/453c6e7ff81c
TCC,对于阿里所提出的柔性事务,网上各种版本,各不一致,
TCC你可以理解为是专门针对于分布式场景的一种实现策略或者说协议,TCC把一个分布式的请求任务拆分成了Try、Confirm、Cancel三个步骤,正常的流程肯定先会执行Try,如果执行没问题,再执行Confirm,如果执行过程中出现了超时或者异常等问题,则执行Cancel操作。从正常的角度去想,这仍然是一种两阶段提交协议的思想,但是其好处是在执行出现问题之后有一定的自我恢复能力,如果任何参与者出现了问题则协调者通过执行操作的逆向操作来回滚之前的所有操作,从而达到最终一致状态。
当然TCC也有它的问题所在,在极端情况下,可能出现有些参与者收到命令,有些没有收到命令的时候,那么系统首先就会通过自动补偿的方式尝试自动修复或者重试,如果无法修复成功则只能由人工参与解决。
其实很多时候我理解分布式服务的一致性一定要以可靠性为基础、简洁性为目标去考量方案,当然前提是满足我们的分布式需求、高并发高性能以及吞吐量为前提。
几种比较高效的处理模式。
主动查询模式;
补偿模式: 异步确保模式;
可靠性消息模式;
定期校对模式;
主动查询模式:
所有的操作都提供一个查询接口,用于向外部输出操作执行的状态,服务操作的使用方可以通过查询接口而得知服务操作执行的状态。然后根据不同的状态来做不同的处理操作。
同步调用超时的场景下使用 。 比如系统A调用系统B但是出现系统A超时的情况,这个时候我们的系统A主动调用发起查询接口,去确认当前调用的处理方(也就是系统B)的真实状态,如果系统B执行的预设任务返回成功,则系统A可以继续执行其他后续逻辑;如果系统B执行的预设任务返回失败,我们可以根据需求进行重试和直接对上游(也就是使用方)返回失败等可确定性的操作。如果系统B执行的预设任务返回未知状态,我们也可以根据实际情况,具体需求去判断到底需不需要重试,重试的话系统B有没有做到幂等,如果调用时间不可容忍也可以采用快速失败策略,然后对系统B去调用业务的逆向操作(或者记录逆向操作日志),然后后续进行回滚和补偿系统B的执行结果,最终达到双方的一致状态。
补偿模式:通常与主动查询模式结合使用,目的都是为了实现上下游的服务最终一致性的努力确保机制。
异步确保模式、可靠消息模式:这两种模式也是互联网行业中经常需要使用的经典模式,很多时候我们的使用方对响应时间 要求不太高、或者说不需要特别强调实时性的场景,这一类的操作我们经常采用异步化、或者解耦的方式,把其从主流程(核心链路上摘除) ,或者说我们划分好业务边界,然后再可以容忍的窗口期内做异步确保和发送可靠性消息模式。这个方案最大的好处是能够对高并发流量进行削峰,从而对服务上能够提供解耦。比如我们电商系统中的物流、配送等,金融系统中的支付、计费入账等等。
定期校对模式:这种方式多用于互联网金融行业,一般都是针对商户与平台与银行等第三方金融支付平台之间的一个经典场景,因为涉及资金安全,所以对于互联网金融行业会对其进行多重的一致性保证机制,比如商户交易对账、系统间一致性对账、财务对账等等。
这种也是针对于场景而言的。一般对实时性要求最低,但是对准确性、一致性要求最高。
关于缓存一致性的问题:
在大规模分布式的系统中,一个场景的核心需求就是亿级别的读需求,显然关系型数据库不是解决高并发的最佳方案,互联网行业通常的做法就是使用缓存来抗住读流量,那么如何保障缓存和数据库的一致性,大概汇总和划分几点必须要做和清楚的事情:
如果性能要求不是非常高,则尽量使用分布式缓存,不要使用本地缓存。
写缓存时数据一定要完整,如果缓存数据一部分有效,另一部分无效,则宁可在需要时回源数据库抽取,也不要把部分数据放入缓存。 使用缓存就牺牲了一致性,为了提高性能,数据库与缓存只能保证且只需要保持弱一致性即可,否则其他的做法即违背了缓存的目的也浪费了太多的系统性能。
读的顺序是先读缓存再读数据库,写的顺序一定要先写数据库再写缓存。