分布式事务

1、分布式事务-解决分布式系统的数据一致性问题

单体应用:service层加事务,基于AOP或声明式注解,基于数据库本身的事务机制,保证数据的原子性。
分布式环境:刚性事务和柔性事务两种处理方式
刚性事务,依然保持要么一起成功,要么一起失败;
柔性事务,追求的是数据的最终一致性,允许存在中间状态,符合BASE理论,基于MQ的方式来实现。

在这里插入图片描述
XA规范:分布式事务规范,定义了分布式事务模型
四个角色:事务管理器(协调者TM)、资源管理器(参与者RM),应用程序AP,通信资源管理器CRM 全局事务:一个横跨多个数据库的事务,要么全部提交、要么全部回滚
JTA事务时java对XA规范的实现,对应JDBC的单库事务

2、实现方案

  1. 两阶段协议在这里插入图片描述
    第一阶段( prepare ) :每个参与者执行本地事务但不提交,进入 ready 状态,并通知协调者已经准备就绪。
    第二阶段( commit ) :当协调者确认每个参与者都 ready 后,通知参与者进行 commit 操作;如果有参与者 fail ,则发送 rollback 命令,各参与者做回滚。
    问题
    单点故障:一旦事务管理器出现故障,整个系统不可用(参与者都会阻塞住)
    数据不一致:在阶段二,如果事务管理器只发送了部分 commit 消息,此时网络发生异常,那么只有部分参与者接收到 commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
    响应时间较长:参与者和协调者资源都被锁住,提交或者回滚之后才能释放
    不确定性:当协事务管理器发送 commit 之后,并且此时只有一个参与者收到了 commit,那么当该参与者与事务管理器同时宕机之后,重新选举的事务管理器无法确定该条消息是否提交成功。

  2. 三阶段协议
    主要是针对两阶段的优化,解决了2PC单点故障的问题,但是性能问题和不一致问题仍然没有根本解决。引入了超时机制解决参与者阻塞的问题,超时后本地提交,2pc只有协调者有超时机制。
    在这里插入图片描述
    第一阶段:CanCommit阶段,协调者询问事务参与者,是否有能力完成此次事务,如果都返回yes,则进入第二阶段;有一个返回no或等待响应超时,则中断事务,并向所有参与者发送abort请求。
    第二阶段PreCommit阶段,此时协调者会向所有的参与者发送PreCommit请求,参与者收到后 开始执行事务操作。参与者执行完事务操作后(此时属于未提交事务的状态),就会向协调者反馈“Ack”表示我已经准备好提交了,并等待协调者的下一步指令。
    第三阶段:DoCommit阶段, 在阶段二中如果所有的参与者节点都返回了Ack,那么协调者就会从“预提交状态”转变为“提交状态”。然后向所有的参与者节点发送"doCommit"请求,参与者节点在收到提交请求后就会各自执行事务提交操作,并向协调者节点反馈“Ack”消息,协调者收到所有参与者的Ack消息后完成事务。 相反,如果有一个参与者节点未完成PreCommit的反馈或者反馈超时,那么协调者都会向所有的参与者节点发送abort请求,从而中断事务。

  3. TCC(补偿事务):Try、Confirm、Cancel
    针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。通过执行逆操作来回滚事务。与两阶段提交不同,补偿事务不要求全局同步,而是在发生错误时执行逆操作。
    Try操作做业务检查及资源预留,Confirm做业务确认操作,Cancel实现一个与Try相反的操作既回滚操 作。TM首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中
    Confirm/Cancel操作若执行失败,TM会进行重试。
    TCC模型对业务的侵入性较强,改造的难度较大,每个操作都需要有 try 、 confirm 、 cancel 三个接口实现和接口还必须实现幂等性。

  4. seata分布式事务 AT模式
    提供了TCC XA AT SAGA事务模式 使用简单 引入依赖,方法加上**@GobalTransationsl注解**
    官方默认使用的是AT模式 协调2个服务 也是2个阶段
    一阶段:业务数据和回滚记录在本地事务中提交,释放锁和连接资源
    二阶段:异步提交,迅速完成。 回滚一阶段的回滚日志进行反向补偿。
    写隔离:一阶段事务提交前,需要确保拿到全局锁 拿不到则不能提交本地事务
    读隔离:数据库本地隔离级别 读已提交,seata的默认全局隔离级别是读已提交。select for update语句代理

  5. 基于可靠消息服务(如RocketMQ)
    采用“两阶段提交”机制,先提交本地事务,再确认消息。如果本地事务成功但消息发送失败,则通过消息队列的重试机制确保消息最终能被消费。
    步骤:
    发送prepare消息到消息中间件发送成功后,执行本地事务;
    如果事务执行成功,则commit,消息中间件将消息下发至消费端(commit前,消息不会被消费);
    如果事务执行失败,则回滚,消息中间件将这条prepare消息删除;
    消费端接收到消息进行消费,如果消费失败,则不断重试。
    优点:支持最终一致性,对消息的顺序性和幂等性有较好的支持。
    缺点:无法保证实时一致性和隔离性。

  6. 本地消息表
    A系统在本地事务操作同时,插入一条数据到消息表,然后将消息发送到MQ中去。B系统接收到消息后,在本地消息表中插入一条数据(数据有唯一约束,避免重复执行),然后执行业务操作。
    优点:实现简单,不需要额外的中间件。
    缺点:严重依赖数据库的消息表来管理事务,无法应对高并发场景。

  7. 最大努力通知方案
    系统A事务执行成功后,把消息放进MQ,然后由专门消费MQ的最大努力通知服务处理。它会先写入到数据库或内存队列,接着调用系统B接口。如果系统B执行失败,就尝试重新调用系统B,反复N次,还是不行就放弃。
    优点:实现简单,适用于对实时性要求不高的场景。
    缺点:无法保证事务的强一致性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值