一、什么是分布式事务
1、概念
在分布式系统上的事务,跨系统的事务称为分布式事务。具体一点,分布式事务是指事务的参与者、支持事务的服务器,资服务器已经事务管理器分别位于不同的分布式系统的不同节点上。
2、分布式事务的难点
事务的原子性:
事务的一致性
事务的隔离性
二、分布式事务的一致性
1、CAP理论
CAP理论是指在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保持一致性(Consistence)、可用性(Availability)、分区容错性(PartitinTolerance)三者中的两个,另外一个必须被牺牲。
C-Consistency一致性:一致性强调客户端读写操作能够获取最新的写操作结果,是因为事务在执行过程中,客户端是无法读取到未提交的数据的,只有等到事务提交后,客户端才能读取到事务写入的数据,而如果事务写入失败,则回滚,客户端也不会读取到事务中间写入的数据。
A-Availability可用性:可用性强调的是合理的响应,不能超时,不能出错。
P-Partition Tolerance分区容忍性:这里网络分区是指:一个分布式系统里面,节点组成的网络本来应该是联通的。然而可能因为一些故障(节点间网络连接断开,节点宕机)使得有些节点之间不连通了,整个网络就分成了几块区域,数据就散布在这些不连通的区域中。
2、一致性、可用性、分区容忍性的选择。
一般来说P一直存在,因为现在微服务都是基于网络交互的,网络的不确定性造成了CAP理论中一定有P。
分布式系统理论上不可能选择CA(一致性+可用性)架构,只能选择CP(一致性+分区容忍性)或者AP(可用性+分区容忍性)架构,在一致性和可用性做折中选择。
3、CAP理论延伸--BASE理论
BASE是指基本可用(Basically Available),软状态(SoftState),最终一致性(Eventual Consistency)。核心思想是即时无法做到强一致性(CAP的一致性就是强一致性),但应用可以采用合理的方式达到最终一致性。
BA-Bascially Availabe基本可用:分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
S-SoftState软状态:允许系统存在中间状态,而该中间状态不会影响系统整体可用性。这里的中间状态就是CAP理论中的数据不一致。
E-Eventual Consistency最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。
BASE理论本质上是对CAP的延伸和补充,更具体的说是对CAP中AP方案的一个补充:
CP理论是忽略延时的,而实际应用中延时是无法避免的。这一点就意味着完美的CP场景是不存在的,即时是几号面的数据复制延迟,在这几毫秒时间间隔,系统是不符合CP要求的。因此CAP中的CP方案,实际上也是实现最终一致性,只是“一定时间”是指几毫秒而言。
AP方案中牺牲一致性只是指发生分区故障期间,而不是永远放弃一致性。这一点其实就是BASE理论延伸的地方,分区期间牺牲一致性,但分区故障回复后,系统应该达到最终一致性。
4、数据一致性模型
分布式系统通过复制数据来提供系统的可靠性和容错性,并且将数据的不同副本存放在不同的机器上,由于维护数据副本的一致性代价很高,因此许多系统采用弱一致性来提高性能
强一致性:要求无论更新操作是在哪个数据副本上执行,之后所有的读操作都要能获取到最新的数据。多副本需要分布式事务协议。
弱一致性:在这种一致性下,用户读到某一操作对系统特定数据的更新需要一段时间,我们将这端时间成为“不一致性窗口”。
最终一致性是弱一致性的一种特例,在这种一致性下系统保证用户最终能够读取到某操作对系统特定数据的更新(读取操作之前没有该数据的其他更新操作)。“不一致性窗口”的大小依赖于交互延迟,系统的负载,以及数据的副本数等。
5、柔性事务
基于BASE理论的设计思想,柔性事务下,在不影响系统整体可用的情况下,允许系统窜在数据不一致的中间状态(Soft State软状态),在经过数据同步的延时之后,最终数据能够达到一致。并不是完全放弃了ACID,而是通过放宽一致性要求,借助本地事务来实现最终分布式事务一致性的同时也保证系统的吞吐量。
特性:
(1)可见性(对外查询)在分布式事务执行过程中,如果某一个步骤执行出错,就需要明确的知道其他几个操作的处理情况,这就需要其他的服务都能够提供查询接口,保证可以通过查询来判断操作的处理情况。
(2)操作幂等,幂等性其实是个数学概念,是指可以使用相同参数重复执行,并能获取相同执行结果的行数。幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。之所以需要幂等性,是为了保证数据的一致性。很多事务已都会有很多重试的操作,如果一个方法不能保证幂等,那么将无法被重试。
三、常见分布式事务解决方案
1、2PC(二段提交)方案--强一致性
方案简介:参与者将操作成败通知协调者,再由协调者根据所有参与者反馈的情况决定是否提交还是中止操作。
处理流程:
(1)请求阶段(表决阶段)事务协调者通知每个参与者准备提交或者取消事务,然后进入表决过程,参与者要么在本地执行事务,写本地的redo和undo日志,但不提交。请求阶段,参与者将告知协调者自己的决策
同意(参与者本地执行成功)或取消(本地作业故障)。
(2)提交阶段(执行)基于第一阶段的结果进行决策:提交或取消。当且仅当所有参与者同意提交事务,协调者才通知所有参与者提交事务,否则协调者通知所有参与者取消事务。
(3)缺点同步阻塞问题(所有参与者都是事务阻塞型);单点故障问题(协调者故障);数据不一致(提交阶段局部网络异常)。
方案总结:
性能问题:所有参与者在事务提交阶段处于同步阻塞装填,占用系统资源,容易导致性能瓶颈
可靠性问题;如果谢帖欧哲存贷单点故障问题,出现故障,参与者将一直处于锁定状态。
数据一致性问题:在阶段2中如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没有收到提交信息,导致节点之间数据不一致。
2、3PC(三阶段提交方案)
方案简介:分布式事务三阶段提交(3PC)在参与者和协调者中都引入超时机制,并且把二段提交的第一部分分为两步:询问,然后在锁资源,最后在真正提交。
处理流程:
(1)canCommit阶段,3PC的canCommit阶段和2PC的请求阶段很像,协调者向参与者发送commit请求,参与者如果可以提交就返回yes,否则返回no。
(2)preCommit阶段,协调者根据参与者canCommit阶段的响应来决定是否进行事务的preCommit操作(所有为yes,有一个no或者超时)。
(3)doCommit阶段,协调者根据参与者preCommit阶段的响应来决定是否提交事务。
方案总结:
优点:相比二阶段提交,三阶段贴近降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免协调者单点问题。阶段3中协调者出现问题时,参与者会继续提交事务。
缺点:数据不一致问题依然存在,当在参与者者受到preCommint请求后等待doCommite指令时,此时如果协调者请求中断事务,而协调者无法与参与者正常通行,会导致参与者继续提交事务,造成数据不一致。
3、TCC(Try-Confirm-Cancel)事务--最终一致性
方案简介:TCC式服务化的二阶段编程模型,其Try,Confirm,Cancel3个方法具有业务编码实现。
Try:Try操作作为一阶段,负责资源的检查和预留
Confirm:操作作为二阶段提交操作,执行真正的业务。
Cancel:是预留资源的取消。
可以理解为SQL事务中的Lock、Commit、Rollback。
处理流程:
(1)Try阶段:从执行阶段来看,与传统事务机制中业务逻辑相同。但从业务角度来看,TCC机制中Try仅是一个初步操作,它和后续的确认一次才能真正构成一个完整的业务逻辑。这个阶段主要完成:完成所有业务检查(一致性);
预留必须业务资源(准隔离性);Try尝试执行业务TCC事务机制已初步操作(Try)为中心的,确认操作(Confirm)和取消操作(Cancel)都是围绕初步操作(Try)而展开。因此Try阶段中的操作,其保障性是最好的,及时失败,仍然有取消操作(Cancel)
假设商品库存为100,购数量为2,这里检查和更新库存的同时,冻结用户购买数量的库存,同事创建订单,订单状态为待确认。
(2)Confirm/Cancel阶段:根据Try阶段服务是否全部正常执行,继续执行确认操作(Confirm)或取消操作(Cancel)。Confirm和Cancel操作满足幂等性,如果COnfirm或Cancel操作执行失败,将会不断重试直到执行完成。
Confirm:当Try阶段服务全部执行正常,执行确认有无逻辑操作。
Cancel:当Try阶段存在服务执行失败,进入Cancel阶段。
方案总结:
优点:
性能提升,具体业务来实现控制资源锁的粒度变小,不会锁定整个资源。
数据最终一致性,基于Confirm和Cancel的幂等性,保证事务最终完成确认或取消保证数据的一致性。
可靠性,解决了XA协议的协调者单点故障问题,由主业务方发起并控制整个业务活动,业务活动管理器也变成了多点, 引入集群。
缺点:TCC的Try,Confirm和Cancel操作功能要按具体业务来实现,业务偶尔度较高,提高了开发成本。
4、本地消息--最终一致性
方案简介:核心思路是将分布式事务拆分成本地事务进行处理。方案通过在事务主动发起额外新建表,事务发起方处理业务和记录事务消息在本地事务中完成,轮询事务消息表的数据发送事务消息,事务被动方基于消息中间件消费事务表中的事务。
这样设计可以避免“业务处理成功”+“”
5、MQ事务--最终一致性
方案简介:基于MQ的分布式事务方案其实是对本地消息表的封装,将本地消息表基于MQ内部,其他方面的协议基本与本地消息表一致。
6、Saga事务--最终一致性
Saga核心思想是将长事务拆分为多个本地短事务,由Saga事务协调器协调,如果正常结束那就正常完成,如果某个步骤失败,则根据相反顺序依次调用补偿操作。
四、总结
2PC/3PC依赖于数据库,能够很好的提供强一致性和强事务性,但相对来说延迟性比较高,比较适合传统的单体应用,在同一个方法中存在跨库操作的情况,不适合高并发和高性能要求的场景。
TCC适用于执行时间确定且较短,实时性要求高,对数据一致性要求高,比如互联网金融企业最核心的三个服务:交易,支付,账务。
本地消息表/MQ事务都适用于事务中参与方支持操作幂等,对一致性要求不高,业务上能容忍数据不一致到一个人工检查周期,事务涉及的参与方,参与环节较少,业务上有对账/校验系统兜底。
Saga事务,由于Saga事务不能保证隔离性,需要在业务层控制并发,适合于业务场景事务并发操作同一资源较少的情况。Saga相比缺少预提交动作,导致补偿动作的实现比较麻烦,例如业务是发送短信,补偿动作则得在发送一次短信说明撤销,用户体验比较差。
Saga事务比较合适用于补偿动作容易处理的场景。