当前位置: 移动技术网 > IT编程>开发语言>Java > 浅谈Spring事务传播行为实战

浅谈Spring事务传播行为实战

2019年09月06日  | 移动技术网IT编程  | 我要评论

spring框架提供了事务管理的标准实现,且可以通过注解或者xml文件的方式声明和配置事务。

通过异步事件的方式解耦服务调用,可以提高程序的响应速度,并且避免因为事务传播行为而导致的事务问题。

本文以一个电商平台包裹出库的业务为实际背景,通过异步事件与线程池的方式解耦嵌套事务,提高程序并发性能;为了便于问题的分析和方案的理解,同时还讲解了spring的事务管理,并着重介绍了几种不同的事务传播行为。

事务小贴士

什么是事务呢?简单来讲事务就是逻辑上的一组操作,这些操作要么都执行,要么都不执行。

什么是事务管理呢?所谓事务管理,其实就是“按照给定的事务规则来执行事务的提交或者回滚操作”。

事务的机制实现很大一部依赖事务日志文件(undo log和redo log)。事务日志是一个与数据库文件分开的文件。它存储对数据库进行的所有更改,并全部记录插入、更新、删除、提交、回退和数据库模式变化。事务日志是备份和恢复的重要组件。

订单出库失败

在订单的包裹出库之前,会将出库指令下发到商城,其中包含包裹寄送的快递信息,以便销售平台展示快递跟踪信息;同时,为了防止前端因为超卖或者重复下单等原因,已经将订单取消,会根据前端商城的返回状态判断订单是否可以出库。

其中,系统交互流程如下,在前端销售平台与wms(仓储管理系统)之间,会有统一的oms(订单管理系统)进行销售单的管理和数据中转。

当前端销售平台收到出库信息以后,会进行如下的校验与操作:

为了防止调用通知服务的时候出现异常,影响包裹出库,调用通知服务的代码是用try-catch语句包裹起来的。

但是,某些订单在出库的时候,还是出现了如下异常,出库失败:

org.springframework.transaction.unexpectedrollbackexception: transaction rolled back because it has been marked as rollback-only

	at org.springframework.transaction.support.abstractplatformtransactionmanager.processrollback(abstractplatformtransactionmanager.java:873)
	at org.springframework.transaction.support.abstractplatformtransactionmanager.commit(abstractplatformtransactionmanager.java:710)
	at org.springframework.transaction.interceptor.transactionaspectsupport.committransactionafterreturning(transactionaspectsupport.java:534)
	at org.springframework.transaction.interceptor.transactionaspectsupport.invokewithintransaction(transactionaspectsupport.java:305)
	at org.springframework.transaction.interceptor.transactioninterceptor.invoke(transactioninterceptor.java:98)
	at org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:186)
	at org.springframework.aop.framework.cglibaopproxy$dynamicadvisedinterceptor.intercept(cglibaopproxy.java:688)

根据事务的传播行为, transaction rolled back because it has been marked as rollback-only 应该是因为被调用的事务回滚了,当调用一方提交事务的时候因为被标记为了 rollback-only ,因此无法正常提交。

spring事务的传播机制

下面我们详细聊一下spring事务的传播机制。

spring的 @transactional 注解可以用于声明方法支持事务,spring底层通过aop的方式实现事务的控制。

@transactional 注解中的 propagation 属性可以用于指定事务的传播行为。

/**
 * the transaction propagation type.
 * <p>defaults to {@link propagation#required}.
 * @see org.springframework.transaction.interceptor.transactionattribute#getpropagationbehavior()
 */
propagation propagation() default propagation.required;

在transactiondefinition定义中包括了如下几个表示传播行为的常量:

  • transactiondefinition.propagation_requires_new: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。不支持当前事务。
  • transactiondefinition.propagation_not_supported: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。不支持当前事务。
  • transactiondefinition.propagation_never:

以非事务方式运行,如果当前存在事务,则抛出异常。不支持当前事务。

  • transactiondefinition.propagation_required: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。支持当前事务。
  • transactiondefinition.propagation_supports: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。支持当前事务。
  • transactiondefinition.propagation_mandatory: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。支持当前事务。
  • transactiondefinition.propagation_nested: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于transactiondefinition.propagation_required。支持当前事务。

这里需要指出的是,前面的六种事务传播行为是 spring 从 ejb 中引入的,他们共享相同的概念。而 propagation_nested 是 spring 所特有的。以 propagation_nested 启动的事务内嵌于外部事务中(如果存在外部事务的话),此时,内嵌事务并不是一个独立的事务,它依赖于外部事务的存在,只有通过外部的事务提交,才能引起内部事务的提交,嵌套的子事务不能单独提交。如果熟悉 jdbc 中的保存点(savepoint)的概念,那嵌套事务就很容易理解了,其实嵌套的子事务就是保存点的一个应用,一个事务中可以包括多个保存点,每一个嵌套子事务。另外,外部事务的回滚也会导致嵌套子事务的回滚。

利用事务传播行为的解决方案

基于上面事务传播行为的讲解,可以将事务的传播行为设置为 propagation_requires_new ,这样当前事务与被调用事务将是两个不同的事务,可以分别提交或者回滚。

在外层事务捕获异常以后执行如下代码,会输出 false ,说明内层事务回滚并未传播给外层事务: transactionaspectsupport.currenttransactionstatus().isrollbackonly()

而在内层事务执行如下代码,会返回 true ,说明内层事务是一个新的事务,在执行改事务的时候,当前事务会被挂起: transactionaspectsupport.currenttransactionstatus().isnewtransaction()

这样就解决了try-catch块抛出异常因事务传播行为导致的当前事务无法提交的问题。

利用多线程的解决方案

我们知道,在不同的线程之间,事务是独立的。对于发送通知消息这样的业务,适合通过抛出事件的方式,然后通过异步监听器进行处理。

其流程如下:

至于事件模型的实现方式,无论是分布式的zookeeper、redis和mq,还是非分布式的guava event bus、spring event都可以,可以根据实际需要选择。其核心原理仍然是发布订阅模式。

参考链接

可能是最漂亮的spring事务管理详解

transaction必知必会

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网