事务咱们都不陌生,咱们常说的事务通常都是指单机事务,即本地事务。那分布式事务是什么?分布式事务就是由多个本地事务组合而成的事务,通常在分布式场景下才会出现。程序员
好比电商平台中,咱们在购物的时候,下单支付这个过程看上去是一鼓作气的,可是背后多是多个系统的分工合做。订单系统、支付系统、物流系统等。这些系统部署在不一样的服务器上,执行的都是各类的事务,对于电商平台来讲,这就是分布式事务。算法
本地事务都好解决,有一套现成的事务机制,分布式事务比本地事务就要复杂多。如何实现分布式事务呢?大概有 3 种解决方式:数据库
XA协议由 Tuxedo 首先提出的,并交给X/Open组织,做为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。----来源百度百科服务器
二阶段提交也叫 2PC ,The two-phase commit protocol。首先在二阶段提交中有两个角色:网络
所谓得两阶段提交就是指投票(voting)和提交(commit) 两个阶段,跟选举制度同样,先投票,再决定。异步
投票阶段,协调者向参与者发起执行事务操做的请求(CanCommit 请求),并等待参与者响应。分布式
参与者接受到请求后,执行事务请求操做,记录日志信息但不提交,记录成功后,向协调者发生 “Yes” 消息,表示赞成提交操做,若不成功,则发送“No” 消息,表示不一样意此次操做。注意这个过程会锁定数据。性能
投票阶段得流程图,大概就是下面这样子:大数据
提交阶段,协调者接受到全部参与者的响应以后,根据返回来的信息状况,向参与者发送提交或回滚请求。日志
若收到的响应消息都是 “Yes”,则向参与者发送 “DoCommit” 消息,参与者完成本地事务的其余操做并释放资源,而后向协调者发送 “HaveCommitted”消息;
若是协调者收到的消息中包含“No”消息或者在规定时间内有参与者没有响应,则向全部参与者发送“DoAbort”消息,此时发送“Yes”的参与者则会根据以前执行操做时的回滚日志对操做进行回滚,而后全部参与者会向协调者发送“HaveCommitted”消息;
提交阶段的流程,大概入下图所示:
二阶段提交协议容易理解,基于 XA 的二阶段提交算法知足事务的 ACID 特性,看上去比较完美,可是缺点仍是挺多的,主要有如下几个问题:
三阶段提交协议(Three-phase commit protocol,3PC)是对二阶段提交(2PC)的改进。解决了二阶段提交的一些问题,三阶段和二阶段提交最大的不一样是引入超时机制和准备阶段。
先来讲说超时机制,在二阶段提交,只有协调者才有超时机制,若是协调者在规定时间内没有接收到参与者的响应,就会根据当前状态提交或者终止整个事务,可是若是协调者挂了,参与者并无超时机制,因此就一直等待,这也是二阶段提交单点故障的问题。在三阶段提交中,同时在协调者和参与者中引入超时机制。若是协调者或参与者在规定的时间内没有接收到来自其余节点的响应,就会根据当前的状态选择提交或者终止整个事务。
三阶段提交其实就是将二阶段提交中的提交阶段一分为二,三阶段提交协议中的具体三阶段是:CanCommit、PreCommit、DoCommit 三个阶段
CanCommit 阶段,CanCommit 阶段与 2PC 的投票阶段相似:协调者向参与者发送请求操做(CanCommit 请求),询问参与者是否能够执行事务提交操做,而后等待参与者的响应;参与者收到 CanCommit 请求以后,回复 Yes,表示能够顺利执行事务;不然回复 No。
PreCommit 阶段,根据二阶段提交中的提交阶段类似,根据 CanCommit 阶段返回的结果,来决定是否能够进行 PreCommit 操做。
这时候就存在两种状况,若是全部参与者都回复 “Yes”,那么执行流程是这样的:
若是有参与者返回 “No”,或者协调者在规定时间内没有收到参与者的响应,那么将执行中断事务操做。流程是这样的:
DoCommit 阶段, 事务真正提交阶段,协调者根据 PreCommit 阶段参与者返回来的信息,决定是进入提交阶段仍是事务中断阶段。
提交阶段流程以下:
事务中断阶段,流程以下:
不论是二阶段提交仍是三阶段提交,都属于强一致性的,知足事务的 ACID 原则。它们都有两个共同的问题:
而基于 MQ 消息的分布式解决方案就不太同样了,它采用的不是强一致性,而是最终一致性,这也就是 BASE 理论。而且咱们直到 MQ 是异步的,因此性能也比较快,能够说完美的解决了上面两种方式带来的问题。
基于 MQ 消息中间件解决分布式事务的思路是这样的:主要是基于 MQ 消息投递的可靠性,将分布式事务发送给 MQ 中间件以后,中间件将事务持久化,这一点很是重要,保证消息不丢失。消费者端异步消费,若是遇到失败状况,因为咱们的消息是持久化的,因此能够根据业务规则不断重试,有必要的话,人工补偿,保证数据最终一致性。
关于基于分布式消息的最终一致性方案,我准备基于 RocketMQ 单独开一个章节,详细聊一聊,这里就很少说了。
欢迎关注公众号【互联网平头哥】。关注这个互联网苟且偷生的程序员,愿你我共同进步,今天最好的是明天最低的要求。