当前位置:首页 > 科技  > 软件

接口中的大事务,该如何进行优化?

来源: 责编: 时间:2023-12-01 17:14:16 211观看
导读作为后端开发的程序员,我们常常会的一些相对比较复杂的逻辑,比如我们需要给前端写一个调用的接口,这个接口需要进行相对比较复杂的业务逻辑操作,比如会进行,查询、远程接口或本地接口调用、更新、插入、计算等一些逻辑,将最

作为后端开发的程序员,我们常常会的一些相对比较复杂的逻辑,比如我们需要给前端写一个调用的接口,这个接口需要进行相对比较复杂的业务逻辑操作,比如会进行,查询、远程接口或本地接口调用、更新、插入、计算等一些逻辑,将最终接口的返回结果给到前端,而经过这么一系列的业务逻辑操作,接口对DB的操作、对代码业务逻辑判断、进行接口调用这些都是需要时间的,而只要这是一个事务操作,每次对数据库进行的交互都会产生一条事务记录。lVJ28资讯网——每日最新资讯28at.com

那么这样就会对我们接口返回的效率产生影响,而且这个影响是随着数据量的增长而增长的,这时候我们就需要对一整个大事务进行拆分,从而提升整体接口的效率。lVJ28资讯网——每日最新资讯28at.com

何为大事务

就拿我最近开发写的一个接口来说吧,大致是这么一个逻辑,我需要根据页面的提交的数据生成一个收款单,整体接口处理的业务如下,我把它们写在了一个接口里,可以理解为这是一个大事物,这个接口执行的时间是相对比较长的,而且将这些逻辑全部写在一个接口里面,本身来说也是不太合理的。lVJ28资讯网——每日最新资讯28at.com

图片图片lVJ28资讯网——每日最新资讯28at.com


lVJ28资讯网——每日最新资讯28at.com

大事务存在的一些问题

并发数据不一致

不加锁的情况下,由于种种原因第一次接口的调用还没执行完,还在等待第三方的调用回写数据,第二次调用又进来对数据进行了更改,第二次调用先执行完,这时候第一次接口调用拿到了第三方接口的返回,去回写状态发现已经被更新,导致无效操作。lVJ28资讯网——每日最新资讯28at.com

加锁容易阻塞

加锁的情况下, 不会出现数据不一致情况,但是由于大事物执行时间较长,容易造成锁超时失效,锁定太多的数据造成阻塞,严重影响效率。lVJ28资讯网——每日最新资讯28at.com

Undo logo事务日志性能问题

容易造成Undo logo日志数据量很大,降低了日志的查询性能,包括对事务的回滚效率也会降低。lVJ28资讯网——每日最新资讯28at.com

并发数据库压力太大

并发量达到一定程度,会对数据库读写造成不小的压力,会堆积大量等待线程。lVJ28资讯网——每日最新资讯28at.com

如何优化大事务

事务里面不要进行远程RPC调用

首先事务里面进行远程的接口调用,如果不采用分布式事务框架,本身就会存在事务不一致的情况,无法进行数据的回滚操作,并发情况下远程服务响应不及时,会出现接口返回不一致问题,当然必须采用异步调用,后面会提到。lVJ28资讯网——每日最新资讯28at.com

编程型事务更加灵活

声明式事务只需要加在方法头加@Transactional注解即可开启事务,但是还是不太灵活,意味着整个方法所进行对数据库操作都要加进事务,当然一次查询也要进入事务,这并不是我们想要的,我们在update、insert操作上进行事务操作,方便进行回滚。lVJ28资讯网——每日最新资讯28at.com

public Boolean transactionCommit(String userName) {    //查询用户    SysUser sysUser = userMapper.selectUserByUserName(userName,null);    transactionTemplate.execute(new TransactionCallbackWithoutResult() {        @Override        protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {            try {                if (null != sysUser) {                    //用户信息状态更新 status更新为1                    userMapper.updateStatus(userName);                }            } catch (Exception e){                //回滚                transactionStatus.setRollbackOnly();            }        }    });    //再次查询    SysUser sysUser1 = userMapper.selectUserByUserName(userName,"1");    /log/.info("状态为1的用户信息"+JSON./toJSONString/(sysUser1));    return  true;}

编程式事务的灵活点在于可以控制事务执行方法,运用transactionTemplate类进行事务操作,查询操作可以写在外面,这样查询获取数据的操作就不会进入mysql事务表。lVJ28资讯网——每日最新资讯28at.com

数据分批处理

对于事务的更新或者插入,前端可能会有批量操作,大规模数据的批量更新、插入也会对事务接口产生影响,一旦其中有更新或插入失败,为了保证事务的一致性,整个操作都要进行回滚;lVJ28资讯网——每日最新资讯28at.com

  • 前端:可以限制数据,对后端接口的访问,可以将数据进行分页,多次请求,可以避免事务提交大量数据。
  • 后端:也可以去数据进行分页处理,例如每次可以限制50条进行操作,如果是新增逻辑,使用Mybatis的批量更新大大提升效率
List<List<ReceivableFeeSaveDTO>> partition = Lists.partition(receivableFeeSaveDTOList, 50);

大事务拆分小事务

可以将一个事务接口,拆分成多个事务接口,并且每个事务接口只做一件事,比如上面的收款单生成接口,金额回写、第三方接口调用、调用后的结果回写都可以抽成一个哥小事务接口。lVJ28资讯网——每日最新资讯28at.com

就好比做一件很复杂的事情,咋一眼看上去很复杂,但是我们把这复杂的步骤,进行多个步骤的拆分,每个阶段完成每个阶段的事情,就可以将整个过程简化,看起来就没那么复杂了。lVJ28资讯网——每日最新资讯28at.com

异步并行处理

重中之重,事务里如果无法避免远程调用,那么肯定是需要进行异步调用,因为无法保证远程接口的及时响应性,CompletableFuture异步编排特性可以用到,task1和task2任务结束后,执行task3。lVJ28资讯网——每日最新资讯28at.com

CompletableFuture<Object> task1 =CompletableFuture.supplyAsync(() -> {    System.out.println("单号check线程" + Thread.currentThread().getId());    //单号check接口 校验失败抛出异常    return "账单实体信息";}, executor);CompletableFuture<Object> task2 = CompletableFuture.supplyAsync(() -> {    System.out.println("收款单生成线程" + Thread.currentThread().getId());    try {        //收款单生成        return “账单编号”;        Thread.sleep(3000);        System.out.println("任务2结束:");    } catch (InterruptedException e) {        e.printStackTrace();    }}, executor); //task1、task2 执行完执行task3 ,需要感知task1和task2的执行结果CompletableFuture<Boolean> future = task1.thenCombineAsync(task2, (t1, t2) -> {    System.out.println("账单金额回写线程" + Thread.currentThread().getId());    // t1 、t2返回判断    //回写返回结果    return ture;}, executor);

总结

可见大事务是我们接口效率低下的罪魁祸首,有时候我们为了快速实现功能,可能会忽略一些关乎于性能的东西,而这些东西是我们能力提升的一个契机。lVJ28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-35873-0.html接口中的大事务,该如何进行优化?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Spring的三种常见Bean的初始化参数机制,你都用对了吗?

下一篇: 如何在 React 中使用 Axios 库

标签:
  • 热门焦点
Top