分布式事务常用模式

分布式事务常用的模式两阶段提交(2PC)、三阶段提交Three-phase commit(3PC)、补偿事务(TCC)、本地消息表。

两阶段提交(2PC)

两阶段提交(2PC)是一种标准化协议,将提交操作分为两个独立单元。此模式需要一个协调器,协调处理分布式服务器之间的活动和同步。

实现方式

阶段1

每个需要提交数据的服务,将数据记录写入Undo Log,返回操作“成功/失败”的消息。

阶段2

在所有事务的参与者都回复“成功”消息后,协调器向每个服务发出“提交”指令,事务参与者进行提交操作,并返回操作"成功/失败”的消息,协调者在收到所有参与者"完成"的消息后,结束事务。

在一阶段中任何参与者返回"终止"的消息,或协调者发现询问超时,协调者会向所有参与者出"回滚"请求。

缺点

二阶段提交执行过程中间,参与处于阻塞状态,任何一个节点超时都将导致其他节点执行“回滚”操作,在策略上略显保守。

三阶段提交/Three-phase commit (3PC)

三阶段提交是2PC的改进版,2PC有很明显的缺点,协调者发出“提交”指令后,某个参与者突然崩溃,在崩溃恢复后,参与者数据会出现不一致。

因此,3PC将2PC的commit的过程1分为2,分成preCommit和commit,参与者收到协调者发送的preCommit指令后,在等待commit时指令时,如果出现超时的,默认也执行commit。

如果事务参与者出现崩溃,会有一个定时补偿机制,任一个参与者收到commit,或者全部参考者都收到preCommit,  则进行commit,否则执行“回滚"。

优点

单点故障后仍能实现数据一致性。 缺点

网络分区问题,协调者发出后preCommit后,网络出现异常,协调者发出”撤销“操作,参与者默认执行了commit。

补偿事务(TCC)

TCC编程模式本质也是一个两阶段协议,不同之处在于TCC编程模式需要与具体业务耦合。

TCC编程模式实现步骤:

1、所有事务参与者都需要实现try、confirm、cancle接口。

2、事务发起者向协调器发出事务请求,协调器调用事务参与者的try方法进行资源预留的操作。

3、如果参与者的try方法进行预留资源的操作失败,协调者调用所有参与者的Cancle方法进行回滚,Cancle方法需要实现幂等,以应对网络引发的重试。

4、如果所有参与者的try方法返回都“OK”,则调用所有参与者的confirm方法,进行业务操作。

5、所有参与者的Confirm方法都返回“OK",协调器将结束分布式事务。

6、如果有参与者的Confirm方法返回”失败“,或网络原因没有收到回执,协调器会进行重试,如果重试失败,则需要事务补偿机制进行数据处理。

以用户转账为例说明TCC操作:

try阶段

预留资源,预留以冻结金额的方式,账户余额保持不变,其他事务不能使用预留资源,只有冻结操作成功,才认为try阶段是成功的。

confirm阶级

执行扣款操作,使用冻结记录更新账户余额。

本地消息表

本地消息表只对所在系统的本地数据库事务负责,对业务所涉及到的子系统,通过消息队列 通知子系统。

消息发起方一张消息表,记录发送的消息及状态,消息表和本地业务数据表处在同一个事务中。通过MQ把消息传递给子系统,消息接收方需要幂等。

子系统接受消息并处理业务,处理成功或失败都需要通知消息发出方,以便确认、补偿或回滚等操作。

生产方和消费方需定时查看本地消息表,处理尚未完成或者失败的消息。

此方案遵循BASE理论所提到的最终一致性,既不像2PC那样复杂,也不会像TCC出现确认或者回滚不了的情况。

优点

通过最终一致性避免了分布式事务。

缺点

消息表与到业务表处在同一个数据库中的一个事务中。