文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring合理使用编程事务提升N倍性能的操作

2024-11-30 11:02

关注

一般我们在spring项目中都是在方法或者是类上添加事务支持,如下使用方式:

@Transactional
public Account deduction(Long id, BigDecimal money) {
  Optional op = accountDAO.findById(id);
  if (!op.isPresent()) {
      throw new RuntimeException("不存在");
  }
  account.setMoney(account.getMoney().subtract(money)) ;
  return accountDAO.saveAndFlush(account) ;
}

以上应该是我们在项目中使用事务的姿势了。这里是方法级别的事务,当方法执行的时候通过动态代理打开事务,执行代码,提交事务/回滚事务,执行的逻辑大体如下:

transaction.begin();
method.invoke(xxxx);
transaction.commit(); / transaction.rollback();

在上面举的示例比较简单,整个操作就是计算扣减金额,然后更新数据。这个业务也就是在保存数据的时候需要使用到事务,其它的一些计算是不需要在一个事务中的。想象下如果我们这里保存操作之上的代码,计算逻辑是个非常复杂的逻辑可能需要消耗好几秒甚至是十几秒而实际保存操作可能就几毫秒就完成了。我们又知道这方法级的事务在执行的时候是要先获取一个Connection对象(数据库连接对象的)然后打开事务(设置自动提交为false,connection.setAutoCommit(false));说到这你应该能想到,从获取一个Connection对象到释放需要几秒甚至是十几秒的时间,而占用的这些时间中大部分的时间都是与事务无关的操作也就是说是不需要事务的,而我们的数据库连接对象本身就是很宝贵及有限的,这就造成了我们系统的资源浪费,系统的吞吐量非常的低。接下来我们就来通过编程的方式控制事务提供系统的吞吐量。

数据库连接配置:

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/x?serverTimezone=GMT%2B8
    username: root
    password: xxxx
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimumIdle: 1
      maximumPoolSize: 1
      autoCommit: true
      idleTimeout: 30000
      poolName: MasterDatabookHikariCP
      maxLifetime: 1800000
      connectionTimeout: 30000
      connectionTestQuery: SELECT 1

注意:这里把数据库连接池配置为1个。

Service中模拟耗时的操作

@Transactional
public Account deduction(Long id, BigDecimal money) {
  System.out.println("Service 当前执行线程:" + Thread.currentThread().getName() + ", id = " + id + ", money = " + money) ;
  Account account = accountDAO.findById(id).orElse(null) ;
  if (account == null) {
    return null ;
  }
  try {
    TimeUnit.SECONDS.sleep(10) ;
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
    account.setMoney(account.getMoney().subtract(money)) ;
  return accountDAO.saveAndFlush(account) ;
}

Controller接口

@GetMapping("/deduction")
public Object deductionAction(Long id, BigDecimal money) {
  System.out.println("Controller 当前线程:" + Thread.currentThread().getName()) ;
  return accountService.deduction(id, money) ;
}

启动两个浏览器测试,观察控制台的输出

图片

两个浏览器都还在转圈,没有响应。

图片

控制台展示Controller方法都进入了,但是Service方法只进入了一个,因为我们的连接池只配置了一个,另外一个在等待可用的连接对象。而上面我也说了,其实Service中很长的一个计算耗时是不需要事务的,即便没有连接对象可用,我们也应该让这些不需要事务的操作也进行执行。接下来修改代码。

@Resource
private TransactionTemplate transactionTemplate ;
    
public Account deduction(Long id, BigDecimal money) {
  System.out.println("Service 当前执行线程:" + Thread.currentThread().getName() + ", id = " + id + ", money = " + money) ;
  Account account = accountDAO.findById(id).orElse(null) ;
  if (account == null) {
    return null ;
  }
  try {
    TimeUnit.SECONDS.sleep(10) ;
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  // 以上业务代码执行可能是个很耗时的操作。
  return transactionTemplate.execute(new TransactionCallback() {
    @Override
    public Account doInTransaction(TransactionStatus status) {
      try {
        account.setMoney(account.getMoney().subtract(money)) ;
          return accountDAO.saveAndFlush(account) ;
      } catch (Exception e) {
        logger.error("发生错误:{}", e) ;
        status.setRollbackOnly() ;
      }
      return null ;
    }
  }) ;
}

这里把方法上的事务注解删了,把需要事务的操作通过编程的方式包装,在Service中注入

TransactionTemplate对象,SpringBoot项目已经自动为我们配置好了,自动装配类:
TransactionAutoConfiguration.java

测试:

图片

浏览器都还在转圈中,查看控制台:

图片

2个Service方法都进去了,基本连接池只有一个连接对象,但是也不妨碍我非事务的代码执行,通过这样的改造,我们的系统吞吐量是不是提升了N呢?

来源:实战案例锦集内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯