【接口优化方案解决】

news2024/12/24 11:29:57

文章目录

  • 前言
  • 1、批量插入或者查询数据库
  • 2、异步思想 耗时操作,考虑放到异步
  • 3、空间换时间思想:恰当使用缓存。
  • 4. 预取思想:提前初始化到缓存
  • 5、借用线程池
  • 6. 事件回调思想:拒绝阻塞等待。
  • 7、锁粒度避免过粗
  • 8、切换存储方式:文件中转暂存数据
  • 9、索引
  • 10、 优化SQL
  • 11、避免大事务的问题
  • 12、 深分页问题
  • 13、优化程序结构
  • 14、压缩传输内容
  • 15、线程池设计要合理
  • 16、机器问题 (fullGC、线程打满、太多IO资源没关闭等等)

前言

	在工作中大家会遇到接口响应慢的问题,导致线上用户在等待,现在总结出了18中接口方案的优化,供大家参考,如果有遗漏请大家也留言补充。

1、批量插入或者查询数据库

随着数据的增加,数据库查询的性能也在增加,因此我们需要优化数据库的每次查询或者插入的数量,来保证数据。
反例:

//直接遍历插入,数据量大,耗时
for(User user :list){
	insert(user);
}

正例

batchInsert(list);//批量插入,每次按照一定的数量进行插入

2、异步思想 耗时操作,考虑放到异步

耗时操作,考虑用异步处理,这样可以降低接口耗时。
反例
在这里插入图片描述

正例
在这里插入图片描述
异步的实现方式,你可以用线程池,也可以用消息队列实现。

3、空间换时间思想:恰当使用缓存。

在适当的业务场景,恰当地使用缓存,是可以大大提高接口性能的。缓存其实就是一种空间换时间的思想,就是你把要查的数据,提前放好到缓存里面,需要时,直接查缓存,而避免去查数据库或者计算的过程。
这里的缓存包括:Redis缓存,JVM本地缓存,memcached,或者Map等等。我

4. 预取思想:提前初始化到缓存

预取思想很容易理解,就是提前把要计算查询的数据,初始化到缓存。如果你在未来某个时间需要用到某个经过复杂计算的数据,才实时去计算的话,可能耗时比较大。这时候,我们可以采取预取思想,提前把将来可能需要的数据计算好,放到缓存中,等需要的时候,去缓存取就行。这将大幅度提高接口性能

5、借用线程池

线程池可以帮我们管理线程,避免增加创建线程和销毁线程的资源损耗。
如果你每次需要用到线程,都去创建,就会有增加一定的耗时,而线程池可以重复利用线程,避免不必要的耗时。 池化技术不仅仅指线程池,很多场景都有池化思想的体现,它的本质就是预分配与循环使用。

6. 事件回调思想:拒绝阻塞等待。

如果你调用一个系统B的接口,但是它处理业务逻辑,耗时需要10s甚至更多。然后你是一直阻塞等待,直到系统B的下游接口返回,再继续你的下一步操作吗?这样显然不合理。
我们参考IO多路复用模型。即我们不用阻塞等待系统B的接口,而是先去做别的操作。等系统B的接口处理完,通过事件回调通知,我们接口收到通知再进行对应的业务操作即可。

7、锁粒度避免过粗

在高并发的情况下,为了保证数据的正确性,需要加锁。
因为加锁的效率肯定会变低,因此锁的范围就显得很重要,因此我们需要更细力度的去加锁,而不是将整个代码块都进行加锁。
反例

Lock lock=new ReentrantLock();
lock.lock
//这里不管有没有数据安全问题都进行加锁
lock.unlock();

反例

Lock lock=new ReentrantLock();
lock.lock
//只锁可能出现数据安全的地方
//这里如果是写出现的数据问题,就加写锁,如果为读出现的问题,就加读锁。
lock.unlock();

8、切换存储方式:文件中转暂存数据

如果数据量太大,就会导致数据库的执行会特别缓慢,这时候要考虑,先保存到本地,然后在去异步写入到数据库。

9、索引

索引优化这块的话,一般从这几个维度去思考:
你的SQL加索引了没?
你的索引是否真的生效?
你的索引建立是否合理?(主要是根据数据量的大小,当前加索引列的更新是否频繁,当前的索引是否太多)

10、 优化SQL

1、select 具体的字段,而不是select *
2、多用limit
3、尽量用union all 代替union
4、优化group by
5、优化order by
6、小表驱动大表
7、字段字段类型使用是否合理
8、优化limit分页
9、exist&in的合理利用
10、join关联的表不宜过多
11、delete+in子查询不走索引
12、in的元素不能太多

11、避免大事务的问题

为了保证数据库数据的一致性,在涉及到多个数据库修改操作时,我们经常需要用到事务。而使用spring声明式事务,又非常简单,只需要用一个注解就行@Transactional
正例

@Transactional
public int createUser(User user){
    //保存用户信息
    userDao.save(user);
    passCertDao.updateFlag(user.getPassId());
    return user.getUserId();
}

反例

@Transactional
public int createUser(User user){
    //保存用户信息
    userDao.save(user);
    passCertDao.updateFlag(user.getPassId());
    sendEmailRpc(user.getEmail());
    return user.getUserId();
}

这样实现可能会有坑,事务中嵌套RPC远程调用,即事务嵌套了一些非DB操作。如果这些非DB操作耗时比较大的话,可能会出现大事务问题。

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

大事务引发的问题主要有:接口超时、死锁、主从延迟等等。因此,为了优化接口,我们要规避大事务问题。我们可以通过这些方案来规避大事务:
RPC远程调用不要放到事务里面
一些查询相关的操作,尽量放到事务之外
事务中避免处理太多数据

12、 深分页问题

深分页问题,为什么会慢?我们看下这个SQL
select id,name,balance from account where create_time> ‘2020-09-19’ limit 100000,10;
limit 100000,10意味着会扫描100010行,丢弃掉前100000行,最后返回10行。即使create_time,也会回表很多次。
我们可以通过标签记录法和延迟关联法来优化深分页问题。
标签记录法
就是标记一下上次查询到哪一条了,下次再来查的时候,从该条开始往下扫描。就好像看书一样,上次看到哪里了,你就折叠一下或者夹个书签,下次来看的时候,直接就翻到啦。
假设上一次记录到100000,则SQL可以修改为:
select id,name,balance FROM account where id > 100000 limit 10;
这样的话,后面无论翻多少页,性能都会不错的,因为命中了id主键索引。但是这种方式有局限性:需要一种类似连续自增的字段。

延迟关联法,就是把条件转移到主键索引树,然后减少回表。优化后的SQL如下:
select acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.create_time > ‘2020-09-19’ limit 100000, 10) AS acct2 on acct1.id= acct2.id;
优化思路就是,先通过idx_create_time二级索引树查询到满足条件的主键ID,再与原表通过主键ID内连接,这样后面直接走了主键索引了,同时也减少了回表。

13、优化程序结构

避免创建不必要的对象,避免数据库查询出来不需要的数据等

14、压缩传输内容

压缩传输内容,传输报文变得更小,因此传输会更快啦。10M带宽,传输10k的报文,一般比传输1M的会快呀。

15、线程池设计要合理

我们使用线程池,就是让任务并行处理,更高效地完成任务。但是有时候,如果线程池设计不合理,接口执行效率则不太理想。
一般我们需要关注线程池的这几个参数:核心线程、最大线程数量、阻塞队列。
如果核心线程过小,则达不到很好的并行效果。
如果阻塞队列不合理,不仅仅是阻塞的问题,甚至可能会OOM
如果线程池不区分业务隔离,有可能核心业务被边缘业务拖垮。

16、机器问题 (fullGC、线程打满、太多IO资源没关闭等等)

有时候,我们的接口慢,就是机器处理问题。主要有fullGC、线程打满、太多IO资源没关闭等等。
之前排查过一个fullGC问题:运营小姐姐导出60多万的excel的时候,说卡死了,接着我们就收到监控告警。后面排查得出,我们老代码是Apache POI生成的excel,导出excel数据量很大时,当时JVM内存吃紧会直接Full GC了。
如果线程打满了,也会导致接口都在等待了。所以。如果是高并发场景,我们需要接入限流,把多余的请求拒绝掉。
如果IO资源没关闭,也会导致耗时增加。这个大家可以看下,平时你的电脑一直打开很多很多文件,是不是会觉得很卡。
文章参考GZH:捡田螺的男孩

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

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

相关文章

考研数据结构:第八章 排序

文章目录 一、排序的基本概念二、插入排序2.1插入排序2.1.1算法思想2.1.2算法实现2.1.3算法效率分析2.1.4算法优化——折半插入排序 2.2希尔排序2.2.1算法思想2.2.2代码实现2.2.3算法性能分析 三、交换排序3.1冒泡排序3.1.1算法思想3.1.2代码实现3.1.3算法性能分析 3.2快速排序…

flutter对数组中某个数据二次加工成单独的数组

如何将数据[2,1,2,2,2,1,2,2,3,2,2,2,2,3,2,2,2,2,2,3,2,4,2,2,1,2,3,2,4,2]加工成 [[2], 1, [2, 2, 2], 1, [2, 2], 3, [2, 2, 2, 2], 3, [2, 2, 2, 2, 2], 3, [2], 4, [2, 2], 1, [2], 3, [2], 4, [2]]。这是实际工作中遇到的问题,UI要求将某一类型数据&#xff…

【无标题】idea 中 SpringBoot 点击运行没反应,按钮成灰色

问题描述 在使用 Spring Boot 开发项目时,可能会遇到一个问题:点击运行按钮后,控制台没有任何输出,项目界面也没有显示。这种情况可能是由多种原因导致的,本文将介绍一些常见的解决方法。 解决方法 首先看下Groovy插…

Nexus 如何配置 Python 的私有仓库

Nexus 可作为一个代理来使用。 针对一些网络环境不好的公司,可以通过配置 Nexus 来作为远程的代理。 Group 概念 Nexus 有一个 Group 的概念,我们可以认为一个 Nexus 仓库的 Group 就是很多不同的仓库的集合。 从下面的配置中我们可以看到&#xff0…

自带云盘的内网即时通讯软件,保障数据在公司局域网内安全流通

在信息时代,很多对于内部机密性要求较高的企业,都不惜成本地选择在内网搭建专属的私有化即时通讯系统。企业员工在内部通讯与协同办公的时候,会分享一些文件、文档等资料, 为了保证所有在通讯软件流通的文件,就需要选…

高性能服务器Nodejs操作Mysql数据库

目录 1 Node 操作 mysql1.2 操作 mysql 数据库 2 Web 开发模式2.1 服务端渲染2.2 前后端分离2.3 如何选择 3 身份认证3.1 Session 认证机制3.2 JWT 认证机制 1 Node 操作 mysql 数据库和身份认证 配置 mysql 模块 安装 mysql 模块 npm install mysql建立连接 const mysql …

Windows下编译boost库

准备工作 下载boost库。官方下载地址:为了避免官方版本下载较慢,可以在这里下载版本为1.78安装Virtual Studio,测试过2013以上的版本都可以编译最新版本的boost库,2013之前的版本没有做过测试。 启动编译 启动vistual studio的命…

云南森林火灾vr消防模拟安全演练系统训练消防员火灾和事故的适应和应对能力

据统计,每一场破坏性地震发生后,会引发次生的灾害,而火灾是其中之一。导致火灾的原因,推测是地震时使供电线路短路,引燃易燃物,火灾就随即发生。所以,在日常生活中,定期的消防演练还是非常必要的, VR消防,是VR公司深圳华锐视点利用VR虚拟现实技术,将VR和…

Unity血条制作

一、使用UGUI制作血条 我一般使用image制作血条,当然,也可以使用滑动组件Slider。image的具体操作步骤如下 普通血条 1、在Hierarchy面板中,创建两个image组件,将其中一个设置为另外一个的子节点 2、在Inspector面板中&#…

F5负载均衡器参与的Kubernetes架构选项介绍

F5负载均衡器在业内有着很高的知名度,因为它不仅是F5的代表作,负载均衡(Load Balance)这一词汇正是由F5发明并引入国内的。当前,F5的能力不断拓展,从早期聚焦F5负载均衡器到现在的分布式云应用架构&#xf…

Android 系统桌面 App —— Launcher 开发

Android 系统桌面 App —— Launcher 开发 Launcher简介 Launcher就是Android系统的桌面,俗称“HomeScreen”也就是我们开机后看到的第一个App。launcher其实就是一个app,它的作用是显示和管理手机上其他App。目前市场上有很多第三方的launcher应用&am…

GAN | 论文精读 Generative Adversarial Nets

提出一个GAN (Generative Adversarial Nets) 1 方法 (1)生成模型G(Generative),是用来得到分布的,在统计学眼里,整个世界是通过采样不同的分布得到的,生成…

2023 百度翻译 爬虫 js逆向 代码

js代码&#xff1a; const jsdom require("jsdom"); const {JSDOM} jsdom; const dom new JSDOM(<!DOCTYPE html><p>Hello world</p>); window dom.window; document window.document; XMLHttpRequest window.XMLHttpRequest;function n(t,…

webpack5(一)

什么是webpack webpack是一个静态资源打包工具&#xff0c;它会以一个或者多个文件作为打包的入口&#xff0c;将整个项目的所有文件编译组合成一个或多个文件输出出去。输出的文件就是变异好的文件&#xff0c;可以在浏览器端运行。一般将 webpack 输出的文件称为 bandle 。 …

HTTP与RPC的取舍

HTTP与RPC的取舍 HTTP和RPC都是常用的网络通信协议&#xff0c;它们各有优劣。选择何种协议&#xff0c;主要取决于应用的需求和场景。 HTTP和RPC都有各自的优点和缺点&#xff0c;首先我们对两种协议进行一个总结。 HTTP协议图 HTTP的优点&#xff1a; 广泛的支持&#xff1…

QT学习笔记-开发环境编译Qt MySql数据库驱动与交叉编译Qt MySql数据库驱动

QT学习笔记-开发环境编译Qt MySql数据库驱动与交叉编译Qt MySql数据库驱动 0、背景1、基本环境2、开发环境编译Qt MySql数据库驱动2.1 依赖说明2.2 MySQL驱动编译过程 3、交叉编译Qt MySql数据库驱动3.1 依赖说明3.3.1 如何在交叉编译服务器上找到mysql.h及相关头文件3.3.2 如果…

SpringCloud学习笔记(四)_ZooKeeper注册中心

基于Spring Cloud实现服务的发布与调用。而在18年7月份&#xff0c;Eureka2.0宣布停更了&#xff0c;将不再进行开发&#xff0c;所以对于公司技术选型来说&#xff0c;可能会换用其他方案做注册中心。本章学习便是使用ZooKeeper作为注册中心。 本章使用的zookeeper版本是 3.6…

数学建模(五)非线性规划

课程推荐&#xff1a; 13 非线性规划算法在数学建模中的应用与编程实现_哔哩哔哩_bilibili 一、非线性规划模型 如果目标函数或约束条件中包含非线性函数&#xff0c;就称这种规划问题为非线性规划问题。一般说来&#xff0c;解非线性规划要比解线性规划问题困难得多。而且&am…

iMX6ULL 库移植 | Libgpiod 库的交叉编译及使用指南(linux)

GPIO口的操作&#xff0c;是很常见的功能。传统的GPIO sysfs接口已被弃用。自Linux 4.8起&#xff0c;内核提供了全新的操作gpio的方式libgpiod&#xff08;C library and tools for interacting with the linux GPIO character device&#xff09;&#xff0c;当然也更高效&am…

YashanDB获强制性国家标准GB 18030-2022最高级别认证

近日&#xff0c;深圳计算科学研究院崖山数据库系统YashanDB V23正式完成了强制性国家标准GB 18030-2022《信息技术 中文编码字符集》适配检测&#xff0c;通过该标准的最高实现级别&#xff08;级别3&#xff09;认证&#xff0c;成为数据库领域首批获得该证书的产品&#xff…