这次我要用编程式事务

1.问题背景

废话不多说,先来一张图

简单描述一下,这里有两个服务,a服务中的方法a1执行时,开启事务(这里用的是注解,声明式事务)。首先通过远程调用b服务,执行方法b1,该方法执行时间较长。a服务就一直等待远程调用的返回值。然后就被阻塞。知道得到返回值,进行后续逻辑,执行完成,提交事务。

这里有什么问题吗?我小白,看了好久,没有发现问题。?,难道是执行远程调用耗时的问题吗?(ps:本编重点不在这儿)

2.存在的问题

为了复现问题,我本地进行了模拟。

    @Transactional
    public void a1() {
        //模拟远程调用
        int status;
        try {
            //线程睡眠10s
            TimeUnit.SECONDS.sleep(10);
        }catch (Exception e){
            e.printStackTrace();
        }
        //后面的后续操作 .....TODO  status为远程调用的返回值。这里偷个懒,直接写了。
        testMapper.updateStatus(status);
    }



随后我启动项目,进行接口测试。返回状态码200。业务也是可以走通的。 访问其他接口也是没有影响。

那么接下来我调整一下,数据库连接池参数。

# 连接池中允许的最大连接数
maximum-pool-size: 1
#池中维护的最小空闲连接数
minimum-idle: 1


我这里为了凸显问题,直接将连接池的最大连接数,最小空闲连接数都设置为1。然后我们再访问a1接口。然后在a1接口阻塞期间再去访问a2接口
什么鬼??,刚刚执行只要21毫秒,现在竟然花了六千多毫秒。 我们前后就只改了一个数据库连接池连接数。很明显,我们执行a1的时候,还未执行完毕,这里一直占用着一个连接,接口a2执行的时候,发现池子中已经没有可用连接了,只能等着人家执行完毕释放连接。但是我们这里的远程嗲用b服务根本没有必要占有数据库连接,这里就造成了资源浪费。就算我们将连接池参数调大一些,但是在并发量比较大的情况下,也会存在暴露这个问题。那么我们这里就不能使用声明式事务了。

3.通过编程式事务解决问题

1.去掉@Transactional注解
2.注入transactionTemplate
@Autowired
TransactionTemplate transactionTemplate;


3.transactionTemplate使用
transactionTemplate.execute(new TransactionCallback<String>({
    @Override
    public String doInTransaction(TransactionStatus status) {
        try {
            return testMapper.updateStatus(status);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动开启事务回滚
            status.setRollbackOnly();
            return null;
        }
    }
});


4.测试

在调用a1接口后,立即调用a2接口,也能很快取得返回值。不会被阻塞。

4.总结

在日常工作中,我们基本上只会用声明式事务,这种方式用起来比较简单。也能解决问题。但是在并发量大的情况下,服务器资源就显得比较紧张。就像这个例子,造成了资源的浪费。同时用户体验也会大大降低。所以在开发项目的时候,能够多考虑一些特殊情况式必然的。等到线上出现问题了。我们再去排查,也许已经晚了。

转载于:https://my.oschina.net/u/3553496/blog/3086185

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值