接口性能优化方法总结

接口性能优化是后端开发人员经常碰到的一道面试题,因为它是一个跟开发语言无关的公共问题。

这个问题既可以很简单,也可以相当复杂。

导致接口性能问题的原因多种多样,不同项目的不同接口,其原因可能各不相同。

下面列举几种常见的性能优化方案:

一、索引优化
不管是查询、新增、修改,一个接口必然会去后端请求数据库,所以直接从sql层面进行优化是在设计时必须考虑的一方面。如果查询的时候经常使用的某些字段没有添加索引,就可以根据条件给某些字段添加索引,然后在看sql的具体耗时。
如果添加上了索引,要看一下这个索引有没有生效要怎么看呢?
答案是:可以使用 EXPLAIN 命令,查看 MySQL 的执行计划,它会显示索引的使用情况。
在这里插入图片描述
这个命令将显示查询的执行计划,包括使用了哪些索引。

如果索引生效,你会在输出结果中看到相关的信息。

通过这几列可以判断索引使用情况,执行计划包含列的含义如下图所示:
在这里插入图片描述
SQL语句没有使用索引,除去没有建索引的情况外,最大的可能性是索引失效了。

以下是索引失效的常见原因:
在这里插入图片描述
二、SQL优化
如果优化了索引之后效果不明显,接下来可以尝试优化一下SQL语句,因为相对于修改Java代码来说,改造SQL语句的成本要小得多。

以下是SQL优化的15个小技巧:
在这里插入图片描述
三、远程调用
有时候,我们需要在一个接口中调用其他多个服务的接口。

例如,有这样的业务场景:

在用户信息查询接口中需要返回以下信息:用户名称、性别、等级、头像、积分和成长值。

其中,用户名称、性别、等级和头像存储在用户服务中,积分存储在积分服务中,成长值存储在成长值服务中。为了将这些数据统一返回,我们需要提供一个额外的对外接口服务。

因此,用户信息查询接口需要调用用户查询接口、积分查询接口和成长值查询接口,然后将数据汇总并统一返回。

调用过程如下图所示:
在这里插入图片描述
调用远程接口总耗时 530ms = 200ms + 150ms + 180ms

显然这种串行调用远程接口性能是非常不好的,调用远程接口总的耗时为所有的远程接口耗时之和。
(1)串行改并行
在这里插入图片描述
调用远程接口的总耗时为200ms,这等于耗时最长的那次远程接口调用时间。

在Java 8之前,可以通过实现Callable接口来获取线程的返回结果。

在Java 8之后,可以通过CompletableFuture类来实现这一功能。

以下是一个使用CompletableFuture的示例:
在这里插入图片描述
(2)数据异构
为了提升接口性能,尤其在高并发场景下,可以考虑数据冗余,将用户信息、积分和成长值的数据统一存储在一个地方,比如Redis。

这样,通过用户ID可以直接从Redis中查询所需的数据,从而避免远程接口调用。
在这里插入图片描述
但需要注意的是,如果使用了数据异构方案,就可能会出现数据一致性问题。

用户信息、积分和成长值有更新的话,大部分情况下,会先更新到数据库,然后同步到redis。

但这种跨库的操作,可能会导致两边数据不一致的情况产生。

redis和数据库如何保证一致性呢?

为了保证Redis和数据库之间的数据一致性,可以采用以下策略:

1)基于事务的一致性: 使用数据库的事务来确保数据库操作的一致性。在操作Redis和数据库时,要么两者都成功,要么都失败,使用数据库的事务可以保证这一点。

2)使用锁: 在并发情况下,可以使用锁来确保数据的一致性。当操作Redis和数据库时,首先获取锁,然后执行操作,最后释放锁。

3)读写直写策略: 在更新数据库后,同时更新Redis。这样,当读取数据时,可以直接从Redis获取,避免了数据库的IO开销。

4)异步串行化: 当更新数据库时,通过消息队列异步通知Redis更新,保证Redis的数据最终是一致的,但不保证实时一致性。

5)失败重试和回滚: 如果Redis或数据库的更新失败,应该有重试机制,并在必要时实现回滚操作。

四、重复调用
在我们的日常工作代码中,重复调用非常常见,但如果没有控制好,会严重影响接口的性能。

 解决方案:可以通过批量查询来优化性能,减少数据库的查询次数。

五、异步处理
核心逻辑可以同步执行,同步写库。非核心逻辑,可以异步执行,异步写库。
异步处理方案

异步处理通常有两种主要方式:多线程和消息队列(MQ)

六、避免大事务
大事务,引发性能的问题
在这里插入图片描述
那么我们该如何优化大事务呢?

为了避免大事务引发的问题,可以考虑以下优化建议:

少用@Transactional注解
将查询(select)方法放到事务外
事务中避免远程调用
事务中避免一次性处理太多数据
有些功能可以非事务执行
有些功能可以异步处理

七、锁粒度
在一些业务场景中,为了避免多个线程并发修改同一共享数据而引发数据异常,通常我们会使用加锁的方式来解决这个问题。

然而,如果锁的设计不当,导致锁的粒度过粗,也会对接口性能产生显著的负面影响。

这里说一下MySQL数据库中的三种锁
表锁:

优点:加锁快,不会出现死锁。
缺点:锁定粒度大,锁冲突的概率高,并发度最低。
行锁:

优点:锁定粒度最小,锁冲突的概率低,并发度最高。
缺点:加锁慢,会出现死锁。
间隙锁:

优点:锁定粒度介于表锁和行锁之间。
缺点:开销和加锁时间介于表锁和行锁之间,并发度一般,也会出现死锁。
锁与并发度
并发度越高,接口性能越好。因此,数据库锁的优化方向是:

优先使用行锁
其次使用间隙锁
最后使用表锁

八、分页处理
调用接口从数据库获取数据需要经过网络传输。如果数据量过大,无论是数据获取速度还是网络传输速度都会受到带宽限制,从而导致耗时较长。

那么,这种情况下该如何优化呢?

答案是:分页处理。

将一次性获取所有数据的请求,改为分多次获取,每次只获取一部分用户的数据,最后进行合并和汇总。

九、加缓存
通常情况下,我们最常用的缓存是:Redis和Memcached。将一些经常查询需要的固定不变的数据加入到缓存中,请求的时候优先从缓存里面去取数据,这样会大大提高接口的查询性能,因为缓存是存在内存中的,避免了大量的数据库查询。

十、分库分表
有时候,接口性能受限的并不是其他方面,而是数据库。

当系统发展到一定阶段,用户并发量增加,会有大量的数据库请求,这不仅需要占用大量的数据库连接,还会带来磁盘IO的性能瓶颈问题。

此外,随着用户数量的不断增加,产生的数据量也越来越大,一张表可能无法存储所有数据。由于数据量太大,即使SQL语句使用了索引,查询数据时也会非常耗时。

那么,这种情况下该怎么办呢?

答案是:需要进行分库分表。

十一、监控功能
优化接口性能问题,除了上面提到的这些常用方法之外,还需要配合使用一些辅助功能,因为它们真的可以帮我们提升定位问题的效率。

开启慢查询日志
通常情况下,为了定位SQL的性能瓶颈,我们需要开启MySQL的慢查询日志。把超过指定时间的SQL语句单独记录下来,方便以后分析和定位问题。

开启慢查询日志需要重点关注三个参数:

slow_query_log:慢查询开关
slow_query_log_file:慢查询日志存放的路径
long_query_time:超过多少秒才会记录日志
通过MySQL的SET命令可以设置:
在这里插入图片描述
加监控
为了在出现SQL问题时能够及时发现,我们需要对系统做监控。

目前业界使用比较多的开源监控系统是:Prometheus。

它提供了监控和预警的功能。
监控如下信息:

接口响应时间
调用第三方服务耗时
慢查询sql耗时
cpu使用情况
内存使用情况
磁盘使用情况
数据库使用情况

链路跟踪
有时候,一个接口涉及的逻辑非常复杂,例如查询数据库、查询Redis、远程调用接口、发送MQ消息以及执行业务代码等等。

这种情况下,接口的一次请求会涉及到非常长的调用链路。如果逐一排查这些问题,会耗费大量时间,此时我们已经无法用传统的方法来定位问题。

有没有办法解决这个问题呢?

答案是使用分布式链路跟踪系统:SkyWalking。
在这里插入图片描述
在SkyWalking中,可以通过traceId(全局唯一的ID)来串联一个接口请求的完整链路。你可以看到整个接口的耗时、调用的远程服务的耗时、访问数据库或者Redis的耗时等,功能非常强大。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces Round 953 (Div. 2) A~F

A.Alice and Books(思维) 题意: 爱丽丝有 n n n本书。第 1 1 1本书包含 a 1 a_1 a1​页,第 2 2 2本书包含 a 2 a_2 a2​页, … \ldots …第 n n n本书包含 a n a_n an​页。爱丽丝的操作如下: 她把所有的…

Web3设计风格的特点和趋势

Web3的设计风格正随着区块链技术和去中心化理念的兴起而逐渐形成自己的特色。Web3的设计风格反映了这一新兴领域的创新精神和对个性化、社区驱动的重视。随着技术的发展和用户需求的变化,Web3的设计风格预计将继续演进。以下是一些Web3设计风格的特点和趋势。北京木…

【启明智显产品介绍】工业级HMI芯片Model3C详解(二)图像显示

Model3C芯片国产自主的工业级高清显示与智能控制 MCU,配备强大的 2D 图形加速处理器、PNG/JPEG 解码引擎,可以满足多种交互设计场景和多媒体互动需求,具备高可靠性、高开放性,可广泛应用于工业自动化控制、HMI人机交互、串口屏、智…

Python低溫半导体电子束量子波算法计算

🎯要点 🎯任意维度求解器,绘制三维投影结果 | 🎯解二维静电场、静磁场 | 🎯狄利克雷、诺依曼条件几何矩阵算子 | 🎯算法模拟低溫半导体材料 | 🎯计算曲面达西流 | 🎯电子结构计算和…

深入探索 Gradle 自动化构建技术(六、Gradle 插件平台化框架 ByteX 探秘之旅)

public void test1(){ //1. Collection 提供了两个方法 stream() 与 parallelStream() List list new ArrayList<>(); Stream stream list.stream(); //获取一个顺序流 Stream parallelStream list.parallelStream(); //获取一个并行流 //2. 通过 Arrays 中的 stream…

使用Spring Boot构建全栈应用程序:从理论到实践

文章目录 引言第一章 项目初始化1.1 使用Spring Initializr生成项目1.2 创建基本项目结构 第二章 后端服务开发2.1 定义实体类2.2 创建Repository接口2.3 实现Service类2.4 创建Controller类 第三章 前端集成3.1 使用Thymeleaf模板引擎3.2 创建前端控制器 第四章 安全配置4.1 S…

AcWing算法基础课笔记——求组合数4

求组合数Ⅳ 用来解决求 C a b C_a^b Cab​的问题&#xff08;没有模运算&#xff09; 解决办法&#xff1a;分解质因数&#xff0c;实现高精度乘法。 C a b a ! b ! ( a − b ) ! C_a^b \frac{a!}{b!(a - b)!} Cab​b!(a−b)!a!​ 其中 a ! a! a!可以用 p p p的倍数来表示…

Linux中web集群-nginx负载均衡及案例

概述 代理&#xff1a;外卖&#xff0c;中介&#xff0c;中间商&#xff0c;用户无法直接做事情&#xff0c;通过中介进行处理 用户–》代理–》节点&#xff0c;后面只有一个节点&#xff0c;一般使用的是nginx代理功能即可&#xff0c;如果是集群就需要使用nginx负载均衡 …

世界名著精选,免费!精选了数百本世界名著,打包带走!

世界名著精选是一款汇集了全球经典文学作品的电子书阅读软件。是一个旨在让经典文学作品更易于接触和阅读的平台。它不仅收录了世界各地的经典名著&#xff0c;还通过现代技术手段&#xff0c;让阅读变得更加便捷和个性化。 软件链接&#xff1a;免费&#xff01;几百种资源&a…

【数据结构与算法】图论 详解

何为完全图、稀疏图、稠密图。 完全图&#xff1a;完全图是一种简单的无向图&#xff0c;其中每对不同的顶点之间都恰好有一条边。对于有n个顶点的完全图&#xff0c;它包含n(n-1)/2条边。在有向图中&#xff0c;如果任意两个顶点之间都存在方向相反的两条边&#xff0c;包含n(…

OA流程节点超时功能

在OA系统中&#xff0c;节点超时功能是一个关键的技术特性&#xff0c;它能够确保流程的顺畅进行&#xff0c;避免任务因为个别环节的延误而影响整体进度。本文将探讨OA系统中节点超时功能的技术实现和优化策略。 参考泛微OA ecology E9 前台设置&#xff1a; 系统管理员在管…

2000年 - 2022年 Fama-French三因子模型数据+代码

Fama-French三因子模型是由著名经济学家尤金法玛&#xff08;Eugene Fama&#xff09;和肯尼斯法兰奇&#xff08;Kenneth French&#xff09;提出的&#xff0c;旨在改进资本资产定价模型&#xff08;CAPM&#xff09;&#xff0c;更全面地解释资产收益率的变化。该模型认为&a…

pytest测试框架pytest-rerunfailures插件重试失败用例

Pytest提供了丰富的插件来扩展其功能&#xff0c;介绍下插件pytest-rerunfailures &#xff0c;用于在测试用例失败时自动重新运行这些测试用例。 pytest-rerunfailures官方显示的python和pytest版本限制&#xff1a; Python 3.8pytest 7.2 或更新版本 此插件可以通过以下可…

CentOS 7 内核 3.10 升级 6.5.2 (RPM 直装 + 源码编译)

方案一 直接基于 RPM 在线升级&#xff08;简单&#xff0c;速度快&#xff09; rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm -y # &#xff08;选项一&#xff09;升级最新版内…

【GD32】从零开始学兆易创新32位微处理器——RTC实时时钟+日历例程

1 简介 RTC实时时钟顾名思义作用和墙上挂的时钟差不多&#xff0c;都是用于记录时间和日历&#xff0c;同时也有闹钟的功能。从硬件实现上来说&#xff0c;其实它就是一个特殊的计时器&#xff0c;它内部有一个32位的寄存器用于计时。RTC在低功耗应用中可以说相当重要&#xf…

Linux操作系统段式存储管理、 段页式存储管理

1、段式存储管理 1.1分段 进程的地址空间&#xff1a;按照程序自身的逻辑关系划分为若干个段&#xff0c;每个段都有一个段名&#xff08;在低级语言中&#xff0c;程序员使用段名来编程&#xff09;&#xff0c;每段从0开始编址。内存分配规则&#xff1a;以段为单位进行分配…

Redis-事务-watch-unwatch

文章目录 1、监视key2、提交事务 1、监视key 打开两个窗口&#xff0c;第一个窗口先监视key&#xff0c;然后开始事务&#xff0c;然后再打开第二个窗口&#xff0c;修改balance为0 2、提交事务 此时事务被打断

分布式定时任务系列10:XXL-job源码分析之路由策略

传送门 分布式定时任务系列1&#xff1a;XXL-job安装 分布式定时任务系列2&#xff1a;XXL-job使用 分布式定时任务系列3&#xff1a;任务执行引擎设计 分布式定时任务系列4&#xff1a;任务执行引擎设计续 分布式定时任务系列5&#xff1a;XXL-job中blockingQueue的应用 …

【深度学习驱动流体力学】计算流体力学算例剖析与实现

目录 一.求解器分类汇总压缩性流动求解器(Compressible Flow Solvers):不可压缩流动求解器(Incompressible Flow Solvers):多相流动求解器(Multiphase Flow Solvers):热传递求解器(Heat Transfer Solvers):其他特殊求解器:其他常见求解器:求解器分类:二.求解器案…

黑马苍穹外卖6 清理redis缓存+Spring Cache+购物车的增删改查

缓存菜品 后端服务都去查询数据库&#xff0c;对数据库访问压力增大。 解决方式&#xff1a;使用redis来缓存菜品&#xff0c;用内存比磁盘性能更高。 key :dish_分类id String key “dish_” categoryId; RestController("userDishController") RequestMapping…