看看别人后端API接口性能优化的方法,那叫一个优雅!

2023-05-31 0 1,033

看看别人后端API接口性能优化的方法,那叫一个优雅!开发人员Lauz 标为隆哥蒙 名品该文第三天数读

他们好,我是爱写标识符的Lauz!

USB能优化对专门从事后端合作开发的老师而言,的确再熟识但是了,有的是子公司将USB操控性加入到考核中。那时和他们谈谈合作开发中常见的USB强化形式。

检索

对查阅他们具体而言会想不到 sql 与否加检索了或是与否走检索了。

他们能透过 explain 指示看下检索的采用情形

explain select * from usero whereuserId like%234

;

SQL强化形式

看看别人后端API接口性能优化的方法,那叫一个优雅!

创建检索准则参照:MySQL检索

深巨集难题

MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL改写。

标签记录法

select  id,name FROM user where id > 100000 limit

 10;

延迟关联法

延迟关联法,就是把条件转移到主键检索树,然后减少回表。强化后的SQL如下:

select  a.id,a.name,a.balance FROM user a INNER JOIN (SELECT b.id FROM user b WHERE b.create_time >2022-05-19 limit

 100000, 10) AS c on a.id= c.id;

先透过create_time二级检索树查阅到满足条件的主键ID,再与原表透过主键ID内连接,这样后面直接走了主键检索了,同时也减少了回表。

采用缓存

缓存是一种空间换天数的思想,把要查的数据,放好到缓存里面,需要时,直接查缓存,而避免去查数据库或是计算的过程

缓存通常有两种:一种是本地缓存也就是 JVM 缓存,另一种是 Memcached/Redis 类的集中式缓存。

采用缓存也能采用预取思想提前把将来可能需要的数据计算好,放到缓存中,等需要的时候,去缓存取就行。能透过定时任务定时去更新缓存。

看看别人后端API接口性能优化的方法,那叫一个优雅!

采用缓存需要考虑几个难题:

缓存的高可用难题。如果缓存宕机,与否会压垮数据库?缓存穿透。虽然缓存没有宕机,但是某些 Key 发生了大量查阅,并且这些Key 都不在缓存里,导致短天数内大量请求压垮数据库。缓存击穿。指两个热点 Key,大并发集中对这两个点进行访问,当这个 Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库。大量的热 Key 过期。某些 Key 失效,大量请求在短天数内写入并压垮数据库,也就是缓存雪崩。缓存和数据库一致性难题。

池化思想

池化思想解决的难题就是避免重复创建对象或创建连接,能重复利用,避免不必要的损耗,毕竟创建销毁也会占用天数。他们常见的线程池、数据库连接池都是池化思想。

他们在写标识符时候能利用这种思想来强化USB操控性,凡是不阻碍主流程的业务逻辑,都能异步化,放到后台去做。

看看别人后端API接口性能优化的方法,那叫一个优雅!

异步处理

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

比如:用户注册成功后,短信邮件通知,也是能异步处理

异步的实现形式,能用线程池、异步注解、异步调用,也能用消息队列实现

List<List<Long>> allIds = Lists.partition(ids,200

);

final

 List result = Lists.newArrayList();

allIds.stream().forEach((batchIds) -> {

   CompletableFuture.supplyAsync(() -> {

result.addAll(remoteCallUser(batchIds));

        return

 Boolean.TRUE;

    }, executor);

})

看看别人后端API接口性能优化的方法,那叫一个优雅!

串行改并行

串行就是,当前执行逻辑必须等上两个执行逻辑结束之后才执行,并行就是两个执行逻辑同时进行。

如果是同步调用,则所消耗的总天数 T=T1+T2 +T3;如果是异步调用,则所消耗的总天数 T=Max(T1, T2,T3)。

串行条件:3 个调用之间没有耦合关系,能并行。如果必须在拿到第 1 个调用的结果之后,根据结果再去调用第 2、第 3 个USB,就不能做异步调用了。

看看别人后端API接口性能优化的方法,那叫一个优雅!看看别人后端API接口性能优化的方法,那叫一个优雅!

批量处理

批量操作数据库,主要是针对同时保存多个数据。

强化前:

//for

循环单笔入库

for

(User user:userList){

insert(user);

}

强化后:

batchInsert(userList);

避免大事务

大事务就是运行天数长的事务。由于事务一致不提交,就会导致数据库连接被占用,即并发场景下,数据库连接池被占满,影响到别的请求访问数据库,影响别的USB操控性,甚至有可能拖垮数据库。

看看别人后端API接口性能优化的方法,那叫一个优雅!

因此,为了强化USB,他们要规避大事务难题。他们能透过这些方案来规避大事务:

RPC远程调用不要放到事务里面查阅相关的操作,尽量放到事务之外事务中避免处理太多数据

锁粒度避免过粗

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

关于锁粒度:就是要锁的范围有多大,不管是jvm锁、redis分布式锁还是数据库锁,只需要在临界资源处加锁即可,不涉及共享资源的,不必要加锁。

错误形式

        //非共享资源        private void notShare()

{

        }

        //共享资源        private void share()

{

        }

        private int wrong()

{

            synchronized (this

) {

                share();

                notShare();

            }

        }

正确形式:

       //非共享资源        private void notShare()

{

        }

        //共享资源        private void share()

{

        }

        private int right()

{

            notShare();

            synchronized (this

) {

                share();

            }

        } 

强化程序结构

强化程序逻辑、程序标识符,是能节省耗时的。比如,程序创建多不必要的对象、或是程序逻辑混乱,多次重复查数据库、又或是实现逻辑算法不是最高效的,甚至出现死循环等等。

复杂的逻辑条件,有时候调整一下顺序,就能让程序更加高效。

有时候死循环是他们自己写的,例如下面这段标识符:

while(true

) {

    if

(condition) {

        break

;

    }

    System.out.println(“do samething”

);

}

如果condition条件非常复杂,一旦出现判断不正确,或是少写了一些逻辑判断,就可能在某些场景下出现死循环的难题。

分库分表

当系统发展到一定的阶段,用户并发量大,会有大量的数据库请求,需要占用大量的数据库连接,同时会带来磁盘IO的操控性瓶颈难题。

此外,随着用户数量越来越多,产生的数据也越来越多,由于数据量太大,sql语句查阅数据时,即使走了检索也会非常耗时。

这时候就要分库分表了。

看看别人后端API接口性能优化的方法,那叫一个优雅!

分库分表主要有两个方向:垂直和水平。

在水平方向(即数据方向)上,分库和分表的作用,其实是有区别的,不能混为一谈。

分库:是为了解决数据库连接资源不足难题,和磁盘IO的操控性瓶颈难题。分表:是为了解决单表数据量太大,sql语句查阅数据时,即使走了检索也非常耗时问题。此外还能解决消耗cpu资源难题。分库分表:能解决 数据库连接资源不足、磁盘IO的操控性瓶颈、检索数据耗时 和 消耗cpu资源等难题。

总结

看看别人后端API接口性能优化的方法,那叫一个优雅!技术虐我千百遍,我待技术如初恋,他们下期再见!他们的点赞、收藏和评论对Lauz非常重要,如该文对你有帮助还请转发支持下,谢谢!

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务