分布式事务是指事务的操作位于不同的节点上,需要保证事务的ACID特性
实现分布式事务的方式
一、两阶段提交(2PC)
TWO-Phase Commit 需要数据库支持,Java组件有 automics
通过引入协调者来协调参与者的行为,
但是这种方式是同步阻塞的
二、补偿事务(TCC)
核心就是针对每一个操作进行注册,出现错误进行回滚和补偿
举个例子,假入Bob要向Smith转账,思路大概是:我们有一个本地方法,里面依次调用 1:首先在Try阶段,要先调用远程接口把Smith和Bob的钱给冻结起来。
2:在Confirm阶段,执行远程调用的转账的操作,转账成功进行解冻。
3:如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法(Cancel)。
三、本地消息表(异步确认)
本地消息表与业务数据表处于同一个数据库中,这样就能利用本地食物来保证对这两个表的操作满足事务特性,并且使用了消息队列来保持最终一致性
1、在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中 2、之后将本地消息表中的消息转发到消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发 3、在分布式事务的操作的另一方从消息队列中读取一个消息,并执行消息中的操作
缺点:消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多问题需要处理
四、MQ事务消息,异步消息
通用性较强,拓展性较高
1、第一阶段Prepared阶段,会拿到消息的地址,第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址进行访问消息,并修改状态 也就是说在业务方法内部要想消息队列提交两次请求,一次发送消息和一次确认消息,如果确认消息发送失败了,RabbitMQ会定期扫描消息集群中的事务消息,发现了Prepared消息,会向消息发送者确认,所以生产方需要实现一个检查接口(check),Rabbit会根据发送端设置的策略来决定是会滚消息,还是继续重新发送确认消息,这样就保证了消息发送与本地事务同时成功或者同时失败
分布式事务具体实现
MQ实现
案例模拟
独立的数据库有着独立的事务,那么两者是无法进行同时回滚的,所以需要使用MQ进行