几种分布式事务实现的方法

两阶段提交(2PC)

两阶段提交(Two-phase Commit,1PC),通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者要真正执行事务

运行过程
准备阶段

协调者询问参与者是否执行成功,参与者发回事务执行结果
image

提交阶段

如果事务在每个参与者都执行成功,事务协调者发送通知让参与者提交事务,否则协调者通知参与者回滚事务
需要注意的是,在准备阶段,参与者执行事务,但是未提交,只有在提交,只有在提交接受收到协调者发送来的通知后,才进行提交或者回滚
image

存在的问题

  • 同步阻塞:所有事务参与者在等待其他参与者响应的时候都处于同步阻塞的状态,无法进行其他操作
  • 单点问题协调者在2PC中起到非常大的作用,发生故障将会造成很大的影响,特别是在阶段二发生故障,所有参与者会一直等待状态,无法完成其他操作
  • 数据不一致,在阶段二,如果协调者只发送部分Commit消息,此时网络发生异常,那么只有部分参与者接受到commit消息,也就是说只有部分参与者提交了事务,使得系统数据不一致
  • 过于保守,任意一个节点失败都会导致整个事务失败,没有完善的容错机制

补偿事务(TCC)

TCC其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作,它分为三个阶段

  • try阶段主要是对业务系统做检测及资源预留
  • confirm阶段主要对业务系统做确认提交,try阶段执行成功confirm阶段,默认confirm阶段是不会出错的:只要try成功,confirm一定成功
  • cancel阶段主要是在业务执行错误,需要回滚的状态下执行的业务,预留资源释放

例子:A向B转账,现在有一个本地方法,里面依次调用

  • 首先在try阶段,要先调用远程接口将A和B的钱冻结起来
  • 在confirm阶段,执行远程调用转账的操作,转账成功进行解冻
  • 失败则调用远程接口对用的回方法(cancel)

优点:

  • 和2PC实现和流程都相对简单一点,但数据一致性比2PC来说相对差一点

缺点:

  • 2,3步都用可能失败。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理

本地消息表(异步确保)

本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务在保证对着两张表的操作满足事务特性,并且使用消息队列来保证最终一致性

  • 在分布式事务操作的一方完成业务数据的操作之后向本地信息表发送一条消息,本地事务能保证这个消息一定会被写入本地消息表中
  • 之后将本地消息表中的信息转发到kafka等消息队列中,如果转发成功则将信息从本地消息表中删除,否则继续重发
  • 在分布式事务操作的另一方从信息队列中读取一个消息,并执行消息中的操作

image

优点:一种非常经典的实现,避免了分布式事务,实现最终一致性
缺点:信息表耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理

MQ事务消息

有一些第三方mq是支持事务消息的,比如RocketMQ,他们支持事务消息的方式也是类似于采用的二阶段提交,但是市面上主流的MQ都是不支持事务消息的,比如Rabbit和kafka都不支持

RocketMQ的大致思路
第一阶段prepared消息,会拿到消息的地址,第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态

也就是说在业务方法中要向消息队列提交两次请求,一次发送消息和一次确认消息,如果确认消息发送失败,RocketMQ会定期扫描消息集群中的事务消息,这时候发现prepared消息,它会向消息发送者确认,所以生产方法需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息,这样就能保证消息发送和本地事务保持一致
image

优点:实现最终一致性,不依赖本地数据库事务
缺点:实现难度大,主流MQ不支持,Rocket事务消息部分代码未开源

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值