后端接口性能优化

1、索引

1.1、忘加索引

通过对线上日志的查询,发现一些SQL的执行时间过长,SQL中where和order by的语句中的字段忘记添加索引

查看索引和表结构:

SHOW INDEX FROM  表名;
SHOW CREATE TABLE 表名

添加索引:

ALTER TABLE 表名 ADD INDEX 索引名(列名);
CREATE INDEX 索引名 ON 表名(列名)

无法修改索引,一旦修改就要先删除后添加

DROP INDEX 索引名 ON 表名 ;

1.2、索引失效

EXPLAIN SELECT *FROM 表名 where 列名='具体值'

 这三列的值可以看见是否使用了索引

1.3、选错索引

可以用FORCE INDEX强制使用具体的某个索引

SELECT *FROM 表名 FORCE INDEX(索引名)  WHERE ...

2、SQL优化

3、远程调用

3.1、并行调用

改串行调用为并行调用

completeFuture类

3.2、数据异构

保存数据冗余的数据异构解决方案,但可能会出现数据一致性问题

4、重复调用

4.1、循环查数据库

当需要批量查询数据库时,不应该改变查询条件多次查询

可以提供一个接口,一次查询达到批量查询的效果

4.2、死循环

while(true) {
    if(condition)  
    break; 
}
System. out. println("do samething");

使用这种写法,当condition满足条件时,能跳出此循环,当一旦不满足该条件则会陷入死循环

4.3、无限递归

递归时,如果不设置的递归深度,在使用递归时的结束条件达不到,也会陷入无限递归中,发生堆栈溢出的结果,所以尽量明确递归的深度,即使结束条件达不到,深度达到也要结束递归

5、异步处理

核心逻辑可以同步执行,同步写库;

非核心逻辑可以异步执行,异步写库;

异步处理通常可以使用线程池和mq

5.1、线程池

将核心逻辑和非核心逻辑提交到不同线程池中执行

但这样也会有缺陷,如果服务器重启或是执行的功能出现异常,无法重试,会出现数据丢失

5.2、MQ

发送mq消息给mq服务器,这样我们只需关注业务执行操作的代码即可

对应服务的去mq服务器消费消息

6、使用大事务

减少使用@Transactional注解

将select查询放到事务外

事务中避免远程调用

事务中避免处理太多数据

有些功能可以非事务执行

有些功能可以异步处理

7、锁粒度

为了防止多个线程并发修改某个共享数据,造成数据不一致的异常情况,我们会使用锁

7.1、synchronized

synchronized关键字给代码加锁,在方法上加锁和在代码块上加锁

加锁时需要将粒度缩小到需要加锁的地方,用代码块加锁替代在方法上加锁

单体式应用可以使用此方法加锁,为了保证服务的稳定性,同一个服务会被部署在多个节点上,即使挂了一个节点,其他节点的服务任然可用,多节点部署避免了因为某个节点挂了导致服务不可用的情况,同时也能分摊整个系统的流量,避免系统压力过大,这时synchronized就不适用了,而需要使用分布式锁:Redis分式锁、Zookeeper分布式锁和数据库分布式锁(表锁、行锁、间隙锁)

8、分页处理

当需要进行大批量数据的查询业务时,可以将一次查询分为多次查询,最后返回时再进行汇总

8.1、同步调用

当远程调用接口对请求耗时有要求,可以使用同步分页调用查询接口

8.2、异步调用

当对本身接口和远程调用接口均有耗时要求,可以使用异步分页请求的方式解决,使用Completablefuture类解决该问题,多个线程异步调用远程接口,最后汇总结果统一返回。

9、加缓存

当并发业务量较大,或者一些频繁请求接口的常用数据,可以使用缓存的方法解决该问题,但同时会带来数据不一致的问题

9.1、Redis缓存

当需要请求一个常访问数据时,可以先在缓存中读取,缓存中不存在再去数据库中请求,但同时需要有一个定时任务,去查询数据库更新Redis保持数据的一致性

9.2、二级缓存

即使使用Redis也是远程请求,可以使用本地的内存作为缓存,省去了远程请求的时间,例如guava、Ehcache、caffeine等缓存框架

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.7.5</version>
</dependency>


<!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.1</version>
</dependency>

cacheManager

@Configuration
@EnableCaching
public class Cacheconfig{
    @Bean
    public CacheManager cacheManager(){
    CaffeinecacheManager caffeinecacheManager =new CaffeinecacheManager();
    //设置需要的属性
      return caffeinecacheManager;
    }
}

 使用@Cacheable注解获取缓存值

@Cacheable(value='',key='')

缺点有:数据更新了,不能及时刷新缓存;如果有多台服务器节点,可能会有多个节点数据不一致的情况。因此存在数据不一致问题,该方法尽量使用在一些数据不敏感数据上。

10、分库分表

接口性能受限,是并发量过大,请求数据库压力过大导致接口性能受限。

通过路由算法计算得到该条数据应存入哪个库哪张表,

分库是为了解决数据库连接资源不足的问题和磁盘IO的性能瓶颈问题

分表是为了解决单表数据量太大,SQL语句查询数据时,即使走索引也非常耗时的问题

访问量大,数据量小可以只分库不分表,相反可以只分表不分库

11、辅助功能

11.1、开启慢查询日志

确定SQL的性能瓶颈,需要开启MySQL的慢查询日志,把超过指定时间的sql语句单独记录下来,方便后面分析和解决问题

参数:

<!--慢查询开关-->
set global_query_log ='on'; 
<!--慢查询日志存放的路径-->
set global_query_log_file ='/user/local/mysql/data/slow.log';
<!--超过多少秒才会记录日志-->
set long_query_time =2;

11.2、开启监控

出现SQL问题时及时发现处理,需要对系统做监控

Prometheus可以用来监控

①接口响应时间;

②调用第三方服务耗时; 

③慢查询SQL耗时

④cpu使用情况

⑤内存使用情况

⑥磁盘使用情况 

⑦数据库使用情况

11.3、链路追踪

当接口中处理很多例如:查询数据库、mq消息、Redis请求、远程服务调用

可以使用skywalking定位性能问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值