两阶段提交是一种尽量保证强一致性的分布式事务,因此它是同步阻塞的,而同步阻塞就导致长时间锁定资源问题,所以总体而言效率低,并且存在单点故障的问题(有可能协调者挂,也有可能协调者和其中的某个服务挂了,协调者就不清楚挂了的那个服务到底是执行没执行事务了),所以在极端情况下还是存在数据不一致的风险。
另外就是2PC其实更适合这种多数据源的情况,并且数据源都是关系型数据库。这样可以让两个数据库中的事务都同时处于prepare阶段,提交的时候两个数据库中的事务一起commit。
3PC(三阶段提交)3PC其实就是比较2PC多了一个预提交阶段,3PC的第一阶段做的事情其实是询问参与者是否有条件执行事务,主要目的就是检查一下是否都可用。第二阶段才是和2PC的第一阶段一样呢。
3PC出现的目的是为了解决,2PC阶段协调组和参与者都挂了之后新选举的协调者不知道当前应该提交还是应该回滚的问题。
如果新的协调者来的时候发现一个参与者处于预提交或提交阶段,代表以及过了,所有参与者的确认阶段,这样就直接提交事务就可以了。
所以说新出现的预提交阶段目的是为了让协调者知道,每个参与者目前都是什么阶段,后面该如何同步各个参与者的状态。
但是3PC还是不能保证,当协调者和某个参与者都挂了的时候,重新连接上的参与者是否已经执行了事务。
TCCTCC和上面的两种方案对比更像是 ,分布式服务之间的事务解决方案。应用面更广一些。
TCC的全称是指:Try、Confirm、Cancel
Try:对事务参与者的资源的锁定与预留。
Confirm:这个阶段是在各个参与者服务中执行真正的事务操作。
Cancel:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是对已经执行的业务执行回滚操作。
这种方式比较繁琐,每一次事务都要定义三个操作,try-confirm-cancel。而且TCC对业务的侵入性比较大,每个业务都要写相应得到撤销方法。而且如果撤销方法有不成功的情况,还有保证幂等。
但是还是有场景使用的,想一些涉及到支付、交易等这种强一致性,但又是多个服务的场景,使用TCC时比较合理的。这样能严格保证分布式事务要么都成功,要么都失败回滚。
本地消息表本地消息表的思想主要是依靠各个服务之间的本地事务来保证的。
就是在服务的本地建立一张消息表,一般是在数据库中。
当执行分布式事务的时候执行完本地操作后,在本地的消息表中插入一条数据。
然后将消息发送到MQ中,下一个服务接收到消息后执行本地操作,操作成功后更新消息表中的状态。
如果下一个服务执行失败了,那么消息表中的状态是不会变的,这样就靠定时任务去刷消息表来进行重试,但是这样需要保证被重试的服务是幂等的,这样就保证最终数据一致。
可靠消息可靠消息实际上指的是靠消息中间件来实现分布式事务。
比如A公司的RocketMQ就用消息中间件实现了分布式事务。
例如A系统会先发一个prepared消息到MQ中,消息发送成功了,再执行本地事务,本地事务执行成功了告诉MQ事务执行成功了。否则发送回滚消息。
B系统接收到prepared消息后开始执行本地事务,事务执行成功了,也是告诉MQ发送执行成功。