现有的分布式事务解决方案

现有的分布式事务解决方案,第1张

现有的分布式事务解决方案
  • XA - 俩阶段提交协议(业务无侵入)
    • 第一阶段 : 事务管理器要求涉及到本次 *** 作流程的所有数据源都执行预提交(preCommit) *** 作,是或否
    • 第二阶段 : 根据第一阶段的返回结果来判断当前所有数据源是全部提交或回滚
    • 优点 : 从流程上我们可以看出来,XA保证数据的强一致性,要么一起提交,要么一起回滚
    • 缺点
      • 数据库必须提供对XA的支持,例如MySQL 5.7以下的版本
      • 受协议约束,事务资源(数据库连接)的锁定周期较长,而且因为事务资源的管理器是数据库本身,我们无法在应用层做处理,所以就导致了我们很难优化其性能
  • TCC(侵入业务)
    • try : 预留业务资源,对当前系统做校验,检查当前系统是否准备好提交,与XA的preCommit类似
    • confirm : 如果try执行成功,则确认执行提交 *** 作
    • cancel : 如果try执行失败,则回滚事务,并释放预留资源
    • 优点 : 给了开发人员更大的施展空间,方便拓展,与XA一样,在强一致性上保持的不错
    • 缺点 : 对业务的侵入性很大,每一个分布式的分支都需要实现try,/confirm/i,cancel *** 作,如果一旦需要改造,那绝对很让人愤怒

  • 基于消息中间件的最终一致性解决方案(最常见的方式)
    我们先介绍第一种,不支持事务的消息队列,例如RabbitMQ
    • 方案包括一个生产者,一个消费者,以及一个校验中心和一张存储消息的表
    • 生产者 : 在开启本地事务时保存一条数据到消息表中,状态置位未消费,事务提交之后将消息发送到队列中
    • 消费者 : 通过订阅队列获取到消息,在消费成功后(事务提交之后)修改消息表中的状态为已消费
    • 校验中心 : 校验中心也可以有俩种实现方式
  1. 定时扫描消息表,俩种结果,发送失败的,发送失败则重新发送成功但是消费者一直消费失败,设定消费失败次数,到达次数后标记该信息,调用生产者再次发送该消息((重新消费次数可设置)),重新计时,再次失败发送预警信息给开发人员,请求人工干预
  2. 创建一个校验中心队列,生产者在发送消息时同时发送一条到校验中心队列中,校验中心会有一个消费者来进行订阅该队列,拿到消息后将消息表中的状态置为处理中,然后定时扫描消息表,如果发现消息在规定时间内没有被消费成功,则再次将消息发送到消费者订阅的队列中,请求重新消费(重新消费次数可设置),重新计时,再次失败则请求人工干预
  • 以上的俩种方式原理都是一样的,但是第二种需要写更多的代码
  • 优点 : 将分布式事务进行拆分成本地事务,避免了分布式事务,实现了最终一致性
  • 缺点 : 需要些大量的代码,如果涉及的不够灵活,可能会给后续的开发和拓展带来不好的体验

第二种,支持事务的消息队列,例如RocketMQ

    • 在开启本地事务之前先发送一条预处理消息(Prepared,很像MyBatis的放注入的处理方式),然后处理本地事务,处理结束后发送确认消息,此时会有俩种结果
  1. 确认消息发送成功,RocketMQ执行提交或回滚策略,生产者方面的流程结束
  2. 确认消息发送失败,RocketMQ内部会定时扫描直接本地事务消息表,查询到Prepared消息,如果当前Prepared消息没有被确认,则会向生产者确认,RocketMQ执行提交或回滚策略
  • 消费者订阅队列消费消息,RocketMQ会一直监测消息是否被成功消费,如果失败则一直重试,达到指定次数后申请人工干预

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5635124.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存