【SpringBoot优雅处理长事务】


前言

在我们日常开发的过程中,如果无脑的使用长事务(运行时间长,长时间未提交的事务,都可以称之为长事务),引发如下的一些危害:

  1. 数据库连接池被占满,应用无法获取连接资源
  2. 容易引发数据库死锁
  3. 数据库回滚时间长

综上,合理的对事务进行拆分,尽量让事务变小,变快,减小事务的颗粒度显得尤为重要;如下,提供三种常见的解决方案;


1、编程式事务

基于底层的API,开发者在代码中手动的管理事务的开启、提交、回滚等操作。在spring项目中我们可以使用TransactionTemplate类的对象,手动控制事务。

@Autowired 
private TransactionTemplate transactionTemplate; 
 
... 

public void save(ArtisanDto artisanDto) { 
    transactionTemplate.execute(transactionStatus -> {
        artisanDao.save(artisanDto);
        //....
        // .....
        return Boolean.TRUE; 
    });
}

使用编程式事务最大的好处就是可以精细化控制事务范围, 所以避免长事务最简单的方法就是不要使用声明式事务@Transactional,而是使用编程式事务手动控制事务范围。

2、手动管理事务

有些情况下,可能需要手动控制事务的开始、提交和回滚等操作。可以通过注入 PlatformTransactionManager 依赖来手动管理事务。

@Autowired
private PlatformTransactionManager transactionManager;

public void longTransactionMethod() {
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());

    try {
        // 长事务的处理逻辑

        transactionManager.commit(status);
    } catch (Exception e) {
        transactionManager.rollback(status);
        throw e;
    }
}

3、方法拆分

使用@Transactional 又想避免产生长事务,建议对我们的方法进行拆分,将不需要事务管理的逻辑与事务操作分开。

@Service
public class ArtisanService{

    public void create(ArtisanDto dto){
        queryData();
        biz();
        save(dto);
    }
  
	//事务操作
    @Transactional(rollbackFor = Throwable.class)
    public void save(ArtisanDto  dto){
        artisanDao.insert(dto);
    }
}

queryData()与biz()不需要事务,我们将其与事务方法save()拆开.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Boot提供了优雅停服的功能,从2.3版本开始,内置了此功能,不需要再自行扩展容器线程池来处理。目前Spring Boot支持的嵌入式web服务器(Jetty、Reactor Netty、Tomcat和Undertow)以及反应式和基于Servlet的web应用程序都支持优雅停机功能。[1] 在Spring Boot项目中,我们可以通过一些方法来实现优雅停服。一种简单且常用的方式是在启动停服时处理相关逻辑,如数据落库、保存状态等。可以通过指定Java项目生成的PID来实现。可以在@SpringBootApplication注解的类中添加一个ApplicationPidFileWriter监听器,将PID写入文件中。然后在关闭服务器时,可以通过@PreDestroy注解的方法来处理结束事务。在这个方法中,可以执行一些需要在服务器关闭前完成的操作。[2] 如果部署到Linux中,可以编写一个shell脚本来执行关闭服务器的操作。可以使用cat命令读取PID文件中的PID,并使用kill命令结束进程。如果使用kill命令结束进程,会向Java程序发送一个信号,当项目接收到这个信号时,会调用@PreDestroy注解标注的方法来关闭服务器。[2] 需要注意的是,当外部流量请求到服务端接口执行业务逻辑时,如果服务端此时执行关机(kill),Spring Boot默认情况下会直接关闭容器(如Tomcat),导致业务逻辑执行失败。在一些业务场景下,可能会出现数据不一致的情况,事务逻辑不会回滚。因此,在优雅停服时需要注意处理这些情况,确保数据的一致性和事务的完整性。[3]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值