接口优化技巧

 

一、背景

针对老项目,去年做了许多降本增效的事情,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用方案

 

二、接口优化方案总结

1.批处理

批量思想:批量操作数据库,这个很好理解,我们在循环插入场景的接口中,可以在批处理执行完成后一次性插入或更新数据库,避免多次 IO。

//for循环单笔入库
list.stream().forEatch(msg->{insert();
});
//批量入库
batchInsert();

2. 异步处理

异步思想:针对耗时比较长且不是结果必须的逻辑,我们可以考虑放到异步执行,这样能降低接口耗时。

例如一个理财的申购接口,入账写入申购文件是同步执行的,因为是 T+1 交易,后面这两个逻辑其实不是结果必须的,我们并不需要关注它的实时结果,所以我们考虑把入账写入申购文件改为异步处理。如图所示:

图片

至于异步的实现方式,可以用线程池,也可以用消息队列,还可以用一些调度任务框架。

3. 空间换时间

一个很好理解的空间换时间的例子是合理使用缓存,针对一些频繁使用且不频繁变更的数据,可以提前缓存起来,需要时直接查缓存,避免频繁地查询数据库或者重复计算。

如果你近期准备面试跳槽,建议在ddkk.com在线刷题,涵盖 一万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题,还有市面上最全的技术五百套,精品系列教程,免费提供

需要注意的事,这里用了合理二字,因为空间换时间也是一把双刃剑,需要综合考虑你的使用场景,毕竟缓存带来的数据一致性问题也挺令人头疼。

这里的缓存可以是 R2M,也可以是本地缓存、memcached,或者 Map。

举一个股票工具的查询例子:

因为策略轮动的调仓信息,每周只更新一次,所以原来的调接口就去查库的逻辑并不合理,而且拿到调仓信息后,需要经过复杂计算,最终得出回测收益和跑赢沪深指数这些我们想要的结果。如果我们把查库操作和计算结果放入缓存,可以节省很多的执行时间。如图:

图片

4. 预处理

也就是预取思想,就是提前要把查询的数据,提前计算好,放入缓存或者表中的某个字段,用的时候会大幅提高接口性能。跟上面那个例子很像,但是关注点不同。

举个简单的例子:理财产品,会有根据净值计算年化收益率的数据展示需求,利用净值去套用年化收益率计算公式计算的逻辑我们可以采用预处理,这样每一次接口调用直接取对应字段就可以了。

5. 池化思想

我们都用过数据库连接池,线程池等,这就是池思想的体现,它们解决的问题就是避免重复创建对象或创建连接,可以重复利用,避免不必要的损耗,毕竟创建销毁也会占用时间。

池化思想包含但并不局限于以上两种,总的来说池化思想的本质是**预分配与循环使用,**明白这个原理后,我们即使是在做一些业务场景的需求时,也可以利用起来。

比如:对象池

6. 串行改并行

串行就是,当前执行逻辑必须等上一个执行逻辑结束之后才执行,并行就是两个执行逻辑互不干扰,所以并行相对来说就比较节省时间,当然是建立在没有结果参数依赖的前提下。

比如,理财的持仓信息展示接口,我们既需要查询用户的账户信息,也需要查询商品信息和 banner 位信息等等来渲染持仓页,如果是串行,基本上接口耗时就是累加的。如果是并行,接口耗时将大大降低。

如图:

图片

7. 索引

加索引能大大提高数据查询效率,这个在接口设计之出也会考虑到,这里不再多赘述,随着需求的迭代,我们重点整理一下索引不生效的一些场景,希望对小伙伴们有所帮助。

具体不生效场景不再一一举例,后面有时间的话,单独整理一下。

图片

8. 避免大事务

所谓大事务问题,就是**运行时间较长的事务,**由于事务一致不提交,会导致数据库连接被占用,影响到别的请求访问数据库,影响别的接口性能。

举个例子:

@Transactional(value ="taskTransactionManager", propagation =Propagation.REQUIRED, isolation =Isolation.READ_COMMITTED, rollbackFor ={RuntimeException.class,Exception.class})publicBasicResultpurchaseRequest(PurchaseRecordrecord){BasicResult result =newBasicResult();//插入账户任务taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_account.type(),TaskEnum.Account_bizType.purchase_request.type()));//插入同步任务taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_sync.type(),TaskEnum.Sync_bizType.purchase.type()));//插入影像件上传任务taskMapper.insert(ManagerParamUtil.buildTask(record,TaskEnum.Task_type.pension_sync.type(),TaskEnum.Sync_bizType.cert.type()));result.setInfo(ResultInfoEnum.SUCCESS);return result;}

上面这块代码主要是申购申请完成后,执行一系列的后续操作,如果现在新增申购完成后,发送 push 通知用户的需求。很有可能我们会在后面直接追加,如下图所示:事务中嵌套 RPC 调用,即非 DB 操作,这些非 DB 操作如果耗时较大的话,可能会出现大事务问题。大数据引发的问题主要有:死锁、接口超时、主从延迟等。

@Transactional(value ="taskTransactionManager", propagation =Propagation.REQUIRED, isolation =Isolation.READ_COMMITTED, rollbackFor ={RuntimeException.class,Exception.class})publicBasicResultpurchaseRequest(PurchaseRecordrecord){BasicResult result =newBasicResult();...pushRpc.doPush(record);result.setInfo(ResultInfoEnum.SUCCESS);return result;}

所以为避免大事务问题,我们可以通过以下方案规避:

1,RPC 调用不放到事务里面

2,查询操作尽量放到事务之外

3,事务中避免处理太多数据

9. 优化程序结构

程序结构问题一般出现在多次需求迭代后,代码叠加形成。会造成一些重复查询、多次创建对象等耗时问题。在多人维护一个项目时比较多见。解决起来也比较简单,我们需要针对接口整体做重构,评估每个代码块的作用和用途,调整执行顺序。

如果你近期准备面试跳槽,建议在ddkk.com在线刷题,涵盖 一万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题,还有市面上最全的技术五百套,精品系列教程,免费提供

10. 深分页问题

深分页问题比较常见,分页我们一般最先想到的就是 limit ,为什么会慢,我们可以看下这个 SQL:

select*from purchase_record where productCode ='PA9044'andstatus=4orderby orderTime desclimit100000,200

limit 100000,200 意味着会扫描 100200 行,然后返回 200 行,丢弃掉前 100000 行。所以执行速度很慢。一般可以采用标签记录法来优化,比如:

select*from purchase_record where productCode ='PA9044'andstatus=4and id >100000limit200

这样优化的好处是命中了主键索引,无论多少页,性能都还不错,但是局限性是需要一个连续自增的字段

11.SQL 优化

sql 优化能大幅提高接口的查询性能,由于本文重点讲述接口优化的方案,具体 sql 优化不再一一列举,小伙伴们可以结合索引、分页、等关注点考虑优化方案。

12. 锁粒度避免过粗

锁一般是为了在高并发场景下保护共享资源采用的一种手段,但是如果锁的粒度太粗,会很影响接口性能。

关于锁粒度:就是你要锁的范围有多大,不管是 synchronized 还是 redis 分布式锁,只需要在临界资源处加锁即可,不涉及共享资源的,不必要加锁,就好比你要上卫生间,只需要把卫生间的门锁上就可以,不需要把客厅的门也锁上。

错误的加锁方式:

//非共享资源
privatevoidnotShare(){
}
//共享资源
privatevoidshare(){
}
privateintwrong(){synchronized(this){share();notShare();}
}

正确的加锁方式:

//非共享资源
privatevoidnotShare(){
}
//共享资源
privatevoidshare(){
}
privateintright(){notShare();synchronized(this){share();}
}

三、最后

我相信很多接口的效率问题不是一朝一夕形成的,在需求迭代的过程中,为了需求快速上线,采取直接累加代码的方式去实现功能,这样会造成以上这些接口性能问题。

变换思路,更高一级思考问题,站在接口设计者的角度去开发需求,会避免很多这样的问题,也是降本增效的一种行之有效的方式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817602.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

几分钟学会TypeScript

目录 一、类型推断和类型注解二.类型注解,声明时指定类型三、类型断言四、基础类型和联合类型字符串数字和浮点类型布尔空和undefined多类型值限定 五、数组 元组 枚举数组元组,?代表可选参数枚举枚举使用 六、函数函数作为参数 七、类、接口与抽象类类访问修饰符类…

蓝桥杯省B组复习(小白篇)

个人经历与感受: 本周六也就是4月13号蓝桥杯竞赛,时间还剩下不到两天,我也是一名大一新生第一次接触这个竞赛,最开始只是单纯的抱着觉得算法有意思于是就开始接触算法,到此时此刻,我也发布了很多有关算法的…

python怎么输出小数

先将整型转换成float型,再进行计算,结果就有小数了。 >>> a 10 >>> b 4 >>> c a/b >>> a,b,c (10, 4, 2) >>> a float(a) >>> d a/b >>> a,b,d (10.0, 4, 2.5) >>> 注意&…

在Linux中查看进程的优先级

在Linux中,可以通过多种方式查看进程的优先级。进程的优先级有两种类型:一个是“nice值”,它是用户空间的优先级,用于影响进程的调度;另一个是“实时优先级”,用于实时任务。以下是几种查看这些优先级的方法…

“AttributeError: module ‘numpy‘ has no attribute ‘float‘”的成功解决方法

问题描述 使用NumPy库时遇到:AttributeError: module numpy has no attribute float. 具体报错提示:np.float was a deprecated alias for the builtin float. To avoid this error in existing code, use float by itself. Doing this will not modify…

前端常用加密小技巧:encode, MD5,JSEncrypt

最近工作的时候,写了一个登录注册相关功能,用到了些加密的东西,特此分享~ 什么是 MD5 MD5(Message Digest 5)是一种加密算法,用于生成数字消息或数据的固定长度(128 位)散列值。它…

螺栓拧紧工具选择——SunTorque智能扭矩系统

智能扭矩系统-智能拧紧系统-扭矩自动控制系统-SunTorque 螺栓拧紧工具的选择遵循以下几点: (1)工艺要求精度。目前拧紧工具有两大类:一类是气动拧紧;另一类是电动拧紧,前者精度较后者精度低,发…

从HashMap了解二叉树、平衡二叉树、红黑树

前言 面试过程中,多多少少会问一点数据结构(二叉树)的问题,今天我们来复习一下二叉树的相关问题,文末总结。 1. 二叉树的由来 在 jdk1.8 之前,HashMap 的数据结构由「数组链表」组成,数组是 Ha…

免费插件集-illustrator插件-Ai插件-批量替换链接图

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件,加强illustrator使用人员工作效率,进行批量替换链接图。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/87890501&am…

SAP NACE V1 销售订单打印配置

在项目上,经常会有一些打印的需求,实现的形式也是五花八门, 有通过写一个打印程序,集成所有打印的,也有通过配置NACE 来完成标准打印输出的 今天我们来记录一下,如何通过NACE 的配置一个标准销售订单的打…

【C++软件调试技术】C++软件开发维护过程中典型调试问题的解答与总结

目录 1、引发C软件异常的常见原因有哪些? 2、排查C软件异常的常用方法有哪些? 3、为什么要熟悉常见的异常内存地址? 4、调试时遇到调用IsBadReadPtr或者IsBadWritePtr引发的异常,该如何处理? 5、如何排查GDI对象泄…

滑动窗口最大值(力扣239)

解题思路:首先是用暴力循环来解,其次便是用队列来模拟这个滑动窗口,同时要自定义三个函数,一个pop用来弹出来保证滑动窗口的移动,同时我们把最大的放在队列口那里,当每次有更大的就把原来的挤出栈外&#x…

Newspaper Premium高级主题:新闻网站的最佳选择,快速、SEO优化与丰富功能

Newspaper Premium高级主题,作为WordPress平台上最畅销且时尚的新闻主题,以其卓越的性能和丰富的功能,深受新闻网站创作者的青睐。无论是新闻中心还是其他利基市场,这款主题都能完美应对,助力您快速搭建起一个引人注目…

openstack安装dashboard后登录网页显示404错误

1. 2.进入该目录vim /etc/httpd/conf.d/openstack-dashboard.conf 增加这一行 WSGIApplicationGroup %{GLOBAL} 重启httpd后就可以访问了

如何在Windows使用固定公网地址SSH远程访问本地Archcraft系统

文章目录 1. 本地SSH连接测试2. Archcraft安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接小结 5. 固定SSH公网地址6. SSH固定地址连接 Archcraft是一个基于Arch Linux的Linux发行版,它使用最简主义的窗口管理器而不是功能齐全的桌面环境来提供图形化用户界面。 C…

推荐两款HTTP请求Mock利器

1、背景 在日常测试过程中或者研发开发过程中,目前接口暂时没有开发完成,测试人员又要提前介入接口测试中,测试人员不仅仅只是简单的编写测试用例,也可以通过一些mock的方法进行来提前根据接口测试的情况进行模拟返回接口的信息&…

赚钱游戏 2.0.1 版 (资源免费)

没有c编辑器的可以直接获取资源来玩 #include <iostream> #include <string> #include <windows.h> #include <conio.h> #include <fstream> #include <ctime> #include <time.h> #include <stdio.h> #include <cstring&g…

redis如何实现故障转移

Redis可以通过以下几种方式实现故障转移&#xff1a; Redis Sentinel&#xff1a;Redis Sentinel是一种自动故障转移解决方案&#xff0c;它由三个组件组成&#xff1a;一个主服务器、一个或多个从服务器和一个监控代理。监控代理负责监控主服务器&#xff0c;并在主服务器出现…

2024年认证杯数学建模C题思路+模型+代码

C题 云中的海盐 巴黎气候协定提出的目标是&#xff1a;在 2100 年前&#xff0c;把全球平均气温相对于工业 革命以前的气温升幅控制在不超过 2 摄氏度的水平&#xff0c;并为 1.5 摄氏度而努力。 但事实上&#xff0c;许多之前的研究已经指出&#xff0c;全球的碳排放以及…

微信小程序支付Java工具类

准备工作 微信支付开发前&#xff0c;需要先获取商家信息&#xff0c;包括商户号、AppId、证书和密钥&#xff1a; 获取商户号&#xff1a;微信商户平台 申请成为商户 > 提交资料 > 签署协议 > 获取商户号&#xff1b;获取AppID&#xff1a;微信公众平台 注册服务号…