- XA - 俩阶段提交协议(业务无侵入)
- 第一阶段 : 事务管理器要求涉及到本次 *** 作流程的所有数据源都执行预提交(preCommit) *** 作,是或否
- 第二阶段 : 根据第一阶段的返回结果来判断当前所有数据源是全部提交或回滚
- 优点 : 从流程上我们可以看出来,XA保证数据的强一致性,要么一起提交,要么一起回滚
- 缺点
- 数据库必须提供对XA的支持,例如MySQL 5.7以下的版本
- 受协议约束,事务资源(数据库连接)的锁定周期较长,而且因为事务资源的管理器是数据库本身,我们无法在应用层做处理,所以就导致了我们很难优化其性能
- TCC(侵入业务)
- try : 预留业务资源,对当前系统做校验,检查当前系统是否准备好提交,与XA的preCommit类似
- confirm : 如果try执行成功,则确认执行提交 *** 作
- cancel : 如果try执行失败,则回滚事务,并释放预留资源
- 优点 : 给了开发人员更大的施展空间,方便拓展,与XA一样,在强一致性上保持的不错
- 缺点 : 对业务的侵入性很大,每一个分布式的分支都需要实现try,/confirm/i,cancel *** 作,如果一旦需要改造,那绝对很让人愤怒
- 基于消息中间件的最终一致性解决方案(最常见的方式)
我们先介绍第一种,不支持事务的消息队列,例如RabbitMQ- 方案包括一个生产者,一个消费者,以及一个校验中心和一张存储消息的表
- 生产者 : 在开启本地事务时保存一条数据到消息表中,状态置位未消费,事务提交之后将消息发送到队列中
- 消费者 : 通过订阅队列获取到消息,在消费成功后(事务提交之后)修改消息表中的状态为已消费
- 校验中心 : 校验中心也可以有俩种实现方式
- 定时扫描消息表,俩种结果,发送失败的,发送失败则重新发送成功但是消费者一直消费失败,设定消费失败次数,到达次数后标记该信息,调用生产者再次发送该消息((重新消费次数可设置)),重新计时,再次失败发送预警信息给开发人员,请求人工干预
- 创建一个校验中心队列,生产者在发送消息时同时发送一条到校验中心队列中,校验中心会有一个消费者来进行订阅该队列,拿到消息后将消息表中的状态置为处理中,然后定时扫描消息表,如果发现消息在规定时间内没有被消费成功,则再次将消息发送到消费者订阅的队列中,请求重新消费(重新消费次数可设置),重新计时,再次失败则请求人工干预
- 以上的俩种方式原理都是一样的,但是第二种需要写更多的代码
- 优点 : 将分布式事务进行拆分成本地事务,避免了分布式事务,实现了最终一致性
- 缺点 : 需要些大量的代码,如果涉及的不够灵活,可能会给后续的开发和拓展带来不好的体验
第二种,支持事务的消息队列,例如RocketMQ
-
- 在开启本地事务之前先发送一条预处理消息(Prepared,很像MyBatis的放注入的处理方式),然后处理本地事务,处理结束后发送确认消息,此时会有俩种结果
- 确认消息发送成功,RocketMQ执行提交或回滚策略,生产者方面的流程结束
- 确认消息发送失败,RocketMQ内部会定时扫描直接本地事务消息表,查询到Prepared消息,如果当前Prepared消息没有被确认,则会向生产者确认,RocketMQ执行提交或回滚策略
- 消费者订阅队列消费消息,RocketMQ会一直监测消息是否被成功消费,如果失败则一直重试,达到指定次数后申请人工干预
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)