接口性能优化方法总结

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

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

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

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

一、索引优化
不管是查询、新增、修改,一个接口必然会去后端请求数据库,所以直接从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的耗时等,功能非常强大。

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
接口测试和性能测试是软件测试中的两个重要方面。它们有不同的流程和目标。 接口测试的流程通常包括以下步骤: 1. 确定接口测试的范围和目标:确定要测试的接口和功能,并明确测试的目标和期望的结果。 2. 准备测试环境和数据:搭建测试环境,准备测试所需的数据和资源。 3. 编写测试用例:根据接口文档或需求规格,编写详细的测试用例,包括正常情况和异常情况的测试。 4. 执行测试用例:按照预定的测试计划,执行测试用例并记录测试结果。 5. 验证和修复缺陷:对测试结果进行验证,如果发现问题或缺陷,及时记录并通知相关人员进行修复。 6. 重复执行测试:对修复后的接口再次执行测试,确保问题解决并正常运行。 7. 生成报告和总结:整理测试结果,生成测试报告,并进行总结和分析,提出改进建议。 性能测试的流程通常包括以下步骤: 1. 确定性能测试的目标和需求:明确要测试的性能指标和期望的性能要求。 2. 设计性能测试方案:根据需求和目标,设计性能测试的场景、负载和测试数据。 3. 准备测试环境和工具:搭建性能测试环境,并选择合适的性能测试工具。 4. 配置和准备测试数据:根据测试方案,配置测试工具和准备测试数据。 5. 执行性能测试:按照设计的测试方案,执行性能测试,并记录相关的性能指标和日志。 6. 分析和优化性能:对性能测试结果进行分析,找出性能瓶颈和问题,并提出优化建议。 7. 生成报告和总结:整理性能测试结果,生成测试报告,并进行总结和分析,提出改进建议。 请注意,以上是一般的流程,具体的流程可能会根据项目的需求和实际情况有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值