Spring 分布式事务实现(上)

简介: Spring 分布式事务实现

基于MQ,JTA实现多服务的分布式事务

image.png


Orderservice监听新订单队列中的消息,获取之后新增订单,成功则往新订单缴费队列中写消息,中间新增订单的过程使用JTA事务管理,当新增失败则事务回滚,不会往新订单缴费队列中写消息;

再比如User service 扣费成功后,往新订单转移票队列写消息,这时Ticket service 正在处理中或者处理中发生了失败,这中间的过程中用户查看自己的余额已经扣费成功,但票的信息却没有,此时可以使用事务失败回滚的方式依次回退,这种叫弱一致性;又或者可以把处理失败的内容发送至一个错误队列中,由人工处理等方式解决,这种叫最终一致性。



使用 Spring JTA

可以使用


  • 如JBoss之类的应用服务器提供的JTA事务管理器
  • Atomikos、Bitronix等库提供的JTA事务管理器


禁止使用JTA

  • 为什么禁用JTA ?
    因为JTA采用两阶段提交方式:
  • 第一次是预备阶段
  • 第二次才是正式提交


当第一次提交出现错误,则整个事务出现回滚,一个事务的时间可能会较长,因为它要跨越多个数据库多个数据资源的的操作,所以在性能上可能会造成吞吐量低。

那既然不使用 JTA,如何实现事务呢?

依次提交两事务:



start MQ transaction


receive message 读取消息

出错时,message transaction直接回滚


start DB transaction


update DB更新数据库

出错时,由于此时database transaction、message transaction都尚未提交,这时虽然已经读取了消息,但只要 MQ 支持事务功能,消息就会被回滚,重新放回MQ,重试重新触发该方法


commit DB transaction

出错时,和上一点原因相同


commit MQ transaction

出错时,database transaction已被提交了,所以无法回滚。MQ 事务尚未提交,所以可直接回滚。这也就是不使用 JTA 时遇到的最大难题。所以 spring 也提供了很多机制保障


消息放回至MQ队列,重试重新触发该方法

当这一步出现错误时,上面的因为已经commit,所以不会rollback


1 多数据源的事务同步解决方案

1.1 XA与最后资源博弈

1.start MQ transaction
2.receive message
# 针对 DB 使用 JTA 事务
3.start JTA transaction on DB
4.update DB
# DB 一阶段提交
5.phase-1 commit on DB transaction
# 当该步出错时,由于DB 还在XA的第一次提交预备状态,DB 还是可以回滚
6.commit MQ transaction  
# 等到 MQ 事务提交完成,才做 DB 二阶段提交
# 该步出错时,因为MQ不是XA方式,提交后无法回滚,虽然 DB 都可以回滚
7.phase-2 commit on DB transaction

1.2 共享资源

适用场景


两个数据源可共享同一底层资源时。

比如ActiveMQ使用DB作为底层资源存储,使用DB的connection控制事务提交,需要数据源支持指定底层资源存储方式。


1.3 最大努力一次提交

依次提交事务,可能会出错,尽量通过AOP或Listener实现事务直接的同步。


1.4 JMS最大努力一次提交+重试

适用场景

其中一个数据源是MQ,并且事务由读MQ消息开始。

利用MQ消息的重试机制,重试的时候需要考虑重复消息。

1.start message transaction
2.receive message
3.start database transaction
# 数据库操作出错,消息会被放回MQ,重试重新触发该方法
4.update database
5.commit database transaction
6.commit message transaction  

这种时候没有问题,都能成功回滚。


1.start message transaction
2.receive message
3.start database transaction
4.update database
5.commit database transaction
# 提交MQ事务出错,消息放回MQ,重试重新触发该方法   
6.commit message transaction


DB 已经提交了,所以这时会重复 DB操作,因为DB transaction不是使用JTA事务管理,所以DB已经commit成功.

那如何避免呢,需要忽略重发消息,比如唯一性校验等手段。


1.5 链式事务管理

定义一个事务链,多个事务在一个事务管理器里依次提交。

依旧可能出错。


相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
3月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
122 1
|
2月前
|
消息中间件 Java 对象存储
数据一致性挑战:Spring Cloud与Netflix OSS下的分布式事务管理
数据一致性挑战:Spring Cloud与Netflix OSS下的分布式事务管理
50 2
|
4月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14933 31
|
3月前
|
Java 微服务 Spring
SpringBoot+Vue+Spring Cloud Alibaba 实现大型电商系统【分布式微服务实现】
文章介绍了如何利用Spring Cloud Alibaba快速构建大型电商系统的分布式微服务,包括服务限流降级等主要功能的实现,并通过注解和配置简化了Spring Cloud应用的接入和搭建过程。
SpringBoot+Vue+Spring Cloud Alibaba 实现大型电商系统【分布式微服务实现】
|
3月前
|
Dubbo Java 调度
揭秘!Spring Cloud Alibaba的超级力量——如何轻松驾驭分布式定时任务调度?
【8月更文挑战第20天】在现代微服务架构中,Spring Cloud Alibaba通过集成分布式定时任务调度功能解决了一致性和可靠性挑战。它利用TimerX实现任务的分布式编排与调度,并通过`@SchedulerLock`确保任务不被重复执行。示例代码展示了如何配置定时任务及其分布式锁,以实现每5秒仅由一个节点执行任务,适合构建高可用的微服务系统。
68 0
|
4月前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
183 5
|
4月前
|
存储 安全 Java
实现基于Spring Cloud的分布式配置管理
实现基于Spring Cloud的分布式配置管理
|
4月前
|
缓存 NoSQL Java
Spring Boot中的分布式缓存实现
Spring Boot中的分布式缓存实现
|
4月前
|
NoSQL Java 调度
在Spring Boot中实现分布式任务调度
在Spring Boot中实现分布式任务调度
|
4月前
|
NoSQL Java Redis
如何在Spring Boot中实现分布式锁
如何在Spring Boot中实现分布式锁