提升后端API性能的几种解决方案

news2024/11/15 8:27:11

🔔目的

提升后端API性能的主要目的是为了提高系统整体的响应速度、并发能力以及可用性。主要原因包括:

  1. 提高用户体验

    后端API性能好可以减少响应延迟,给用户流畅的体验。

  2. 提高系统吞吐量

    优化API性能可以提高系统的整体吞吐量,处理更多用户请求。

  3. 节省服务器资源成本

    优化API提高资源利用率,减少对计算、内存、网络等资源的占用。

  4. 提高系统稳定性

    良好的API性能可以防止请求积压造成的链路阻塞,减少超时、服务降级等问题。

  5. 促进业务发展

    性能良好的API可以支撑更复杂的业务场景,为产品迭代和业务增长提供保障。

  6. 提升运维效率

    代码和架构优化可以降低重复工作量,减少故障排查时间。

  7. 增强系统容错能力

    优化后可以应对更大的流量冲击和失效情形。

🔔优化概述

  1. 代码优化

    通过算法优化、减少IO等方式优化程序,使其高效运行。

  2. 缓存使用

    通过Redis、Memcache等缓存数据库缓存常用数据,减少数据库查询。

  3. CDN加速

    使用CDN缓存静态资源,减少服务器压力。

  4. 异步处理

    通过消息队列、事件驱动等方式实现异步处理,提高并发能力。

  5. 服务拆分

    将服务拆分为小的单元服务,采用微服务架构。

  6. 流量控制

    通过限流、降级等方式控制流量并保护服务稳定运行。

  7. 数据库优化

    优化数据库模式,使用索引、读写分离等技术提升数据库效率。

  8. 并发优化

    通过线程池、非阻塞IO等方式提升系统并发性能。

  9. 服务器扩容

    垂直扩容服务器或利用云服务横向扩容,增强处理能力。

🔔具体实践

  • 线程池化

    池化技术(Pooling)的关键思想就是重用,其目的是为了避免每次需要资源时都要重复创建和销毁,从而提高性能和资源利用率。
    以数据库连接池为例,不使用连接池的时候,每次操作数据库都需要:

    1. 创建数据库连接
    2. 执行sql语句
    3. 关闭数据库连接

    这样重复创建和关闭连接会非常耗费资源。
    而引入连接池后,可以提前创建好一定数量的连接,放入连接池待用。需要时直接从池中取出已有连接使用,操作完毕再放回池中,而不需要重复创建连接。
    同样,线程池也是提前创建线程,组成线程池待用,需要时直接派一个空闲线程执行任务,从而避免了频繁创建和销毁线程的资源消耗。
    池化技术重在提高资源的重复利用率。目的是为了提高性能,减少不必要的性能开销。现在几乎所有的连接资源都会使用池化技术进行管理。

  • 批量入库

    对于需要批量插入或者更新到数据库的操作,可以先批量处理逻辑完之后再统一一次性插入数据库,这样做的优势在于

    1. 减少网络交互,提高写入效率

      向数据库批量插入可以减少客户端与数据库之间的网络往返。

    2. 可以对数据进行预处理。

      可以在入库前对数据进行过滤、转换等优化。

    3. 减少索引更新开销

      可以关闭索引,批量插入后再重建索引,从而减少索引更新带来的开销。

    4. 可以执行更复杂的SQL逻辑。

      批处理可以构建更复杂的SQL逻辑完成数据导入。

    5. 提高数据库并发能力。

    批量写入可以聚合成少量大事务,可以减少数据库并发Transaction的数量。

  • 异步执行

    在设计接口时,对于一些非核心业务逻辑,如果这部分逻辑执行时间长且不影响主业务流程,我们可以考虑“异步”执行这些逻辑。
    具体来说,可以通过以下技术方案实现:

    1. 使用消息队列,让主业务逻辑快速返回,将非核心逻辑作为消息放入队列异步执行。

    2. 设计异步线程或定时任务,在主线程返回后,异步线程负责后台执行非核心逻辑。

    3. 利用事件编程模型,主业务逻辑触发事件,事件监听者异步响应事件执行非核心逻辑。

    4. 非核心逻辑作为微服务单独部署,主业务快速调用微服务,微服务后台异步执行逻辑。

    5. 使用reactor模式,主线程接收请求触发非核心逻辑,再通过多线程异步执行非核心处理。

    常见的异步有:

    • 多线程 - 在新线程中执行异步任务,主线程不等待异步线程结束即返回。
    • 事件/回调 - 主线程注册回调,异步任务完成后由系统调用回调函数,通知主线程。
    • Future/Promise - 主线程返回一个future对象,异步线程设置future的结果,主线程可以获取future的结果。
    • Reactor模式 - 基于事件循环的模型,主线程接收请求,dispatch事件给异步线程池处理。
      -消息队列 - 主线程产生消息,通过消息队列进行异步处理。如 RabbitMQ, Kafka。
    • Observable - 主线程注册Observer,由Observable异步调用Observer的回调方法。如 RxJava。
    • Async/Await - 使用async标记的函数自动异步执行,await可以等待异步函数结果。
    • 协程 - 可以手动控制协程的切换,实现异步处理。如Goroutine。
  • 使用缓存

    恰当地使用缓存,可以大大的提升接口的性能。

    使用缓存的主要好处有:

    1. 减少数据库查询,降低后端负载
      缓存可以存储热点数据,减少对数据库的查询,降低后端存储系统的压力。

    2. 加速读取速度
      从缓存读取数据比数据库查询要快得多,可以显著提高访问速度。

    3. 改善用户体验
      加速系统响应,用户会感受到更流畅的用户体验。

    4. 提高系统扩展能力
      缓存层可以作为数据库前的缓冲层,让系统支持更高的负载。

    5. 降低基础设施成本
      减少存储系统扩容提升需求,降低整体IT成本。

    6. 保护核心数据系统
      缓存可充当外部系统与核心存储之间的屏障。

    7. 帮助实现高可用性
      缓存可作为备份数据源,在主数据源不可用时提供冗余数据访问。

    常见的缓存有:

    • Redis - 基于内存的键值缓存,支持多种数据结构,性能极高。

    • Memcached - 简单的内存键值缓存,没有Redis丰富的数据结构。

  • 慢查询优化

    可以从以下几点优化:

    1. 数据库结构优化
      • 合理设计表结构,避免冗余数据。
      • 对于高并发修改的字段,拆分到单独表中。
      • 对访问频繁的列建立索引。
    2. SQL语句优化
      • 尽量避免全表扫描,先通过索引字段过滤数据。
      • 避免在索引列上做函数转换。
      • 对多个表Join时,保证Join条件列有索引。
      • 合理利用慢查询日志分析和调优查询。
    3. 数据库参数优化
      • 调整max_connections、table_open_cache等系统变量。
      • 调整innodb_buffer_pool_size、innodb_log_file_size等InnoDB存储引擎参数。
    4. 架构优化
      • 对热点数据进行缓存。
      • 对可读数据库使用主从复制分离读写。
      • 拆分数据库,分散压力。
      • 使用索引代替Join查询。
    5. 程序优化
      • 避免N+1问题,使用Join提前预加载关联数据。
      • 避免频繁小请求数据库,可以批处理或异步处理。
  • 锁粒度避免过粗

    在设计并发程序时,使用锁(mutex)来保护共享资源,但锁的范围不能设计得过于宽泛,这称为锁的粒度问题。
    过粗的锁粒度意味着锁的范围过于宽泛,例如对整个应用只有一把大锁。这会带来以下问题:

    1. 锁争用过于频繁,并发程度低

    2. 可能会发生死锁

    3. 锁的获取和释放频繁上下文切换,性能消耗严重

    因此需要注意锁粒度的选择:

    1. 只在访问共享资源时加锁,不要锁住无关代码

    2. 可以将一个大锁拆分为多个细粒度的锁

    3. 根据代码逻辑设计锁的范围,避免锁过多或过少

    4. 不同的线程访问不同资源应该用不同的锁

    示例

    private void A(){
    }
    
    //共享方法
    private void B(){
    }
    
    private int C(){
        synchronized(this){
          A();
          B();
        }
    }
    

    修改为

    private void A(){
    }
    
    //共享方法
    private void B(){
    }
    
    private int C(){
    	A();
        synchronized(this){
        B();
        }
    }
    
  • 串行改并行

    在设计程序时,原本采用了串行逻辑,即一个任务完成后再执行下一个任务。这种模型导致任务只能顺序执行,整体吞吐量受到限制。
    为提高吞吐量,可以考虑将程序逻辑改为并行执行。具体做法是:

    1. 把任务进行拆分,同一类任务使用多个实例并行地执行。
    2. 对于需要顺序的任务,可以使用消息队列将任务异步化,提高并行程度。
    3. 对串行的业务流程进行重构,看哪些环节可以通过多线程、异步来并行执行。
    4. 对串行访问的共享资源,使用锁或CAS算法来控制并发访问。
    5. 使用线程池、actor模型等并发框架,提高程序对多核CPU的利用率。
      通过程序逻辑从串行改为并行,可以显著提升系统整体的吞吐量和处理能力。需要注意资源竞争和死锁等并发问题。适当保留关键串行流程来实现正确性。

    比如 串行

    1111725d79c854c85d6e8937c10a304

    改成

    并行

    image-20231010170351945

🔔写在最后

如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

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

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

相关文章

wps演示时图片任意位置拖动

wps演示时图片任意位置拖动 1.wps11.1版本,其他版本的宏插件可以自己下载。2.先确认自己的wps版本是不是11.13.检查是否有图像工具4.检查文件格式和安全5.开发工具--图像6.选中图像控件,右击选择查看代码,将原有代码删除,将下边代…

经典面试题第十更---instanceof与typeof

前言: 🤡 作者简介:我是Morning,计算机的打工人,想要翻身做主人 🙈 🙈 🙈 🏠 个人主页: Morning的主页 📕系列专栏: 前端…

「Qt中文教程指南」如何创建基于Qt Widget的应用程序(二)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 本文描述了如何使用…

计算机毕业设计选什么题目好?springboot 班级事务管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

JS里字符串全部替换

突然在需要处理一个字符串,使用了替换函数之后,发现只替换了第一个位置的字符串,如下结果: 就想要全部替换,可以这样处理: 使用 str.replace(/需要替换的字符串/g,"新字符串")或者使用replaceA…

CSP-J/S第二轮认证注意事项

金九银十日,复赛进行时。 CSP-J/S复赛马上就要开始了,但是每年都有很多孩子因为一些不起眼的失误导致一年的努力付之东流。下面为大家准备了一些复赛的注意事项,避免踩坑。 在哪里写代码 第二轮比赛与我们平时在OJ上做题形式不同&#xff0…

数据挖掘实战(3):如何对比特币走势进行预测?

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…

案例(部门管理和员工管理)-(2)

一、新增员工 1.Controller层 PostMappingpublic Result save(RequestBody Emp emp){log.info ( "新增员工,emp:{}",emp );empService.save(emp);return Result.success ();}2.Service层 Overridepublic void save(Emp emp) {emp.setCreateTime ( LocalDateTime.now …

新手如何快速上手HTTP爬虫IP?

对于刚接触HTTP爬虫IP的新手来说,可能会感到有些困惑。但是,实际上HTTP爬虫IP并不复杂,只要掌握了基本的操作步骤,就可以轻松使用。本文将为新手们提供一个快速上手HTTP爬虫IP的入门指南,帮助您迅速了解HTTP爬虫IP的基…

mysql面试题36:MySQL的binlog有几种录入格式?分别有什么区别

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:MySQL的binlog有几种录入格式?分别有什么区别 MySQL的binlog(二进制日志)是用于记录数据库的更改操作的一种机制,它可以用于数据恢复、数据复…

linux安装filebeat并收集日志到elasticsearch

摘要: 通过filebeat收集服务器上各个应用的日志到elasticsearch,通过tags区分不同的应用创建不同的索引保存日志。 官网地址: https://www.elastic.co/cn/downloads/past-releases#filebeat 安装步骤: 1:下载并解…

【LeetCode高频SQL50题-基础版】打卡第5天:第26~30题

文章目录 【LeetCode高频SQL50题-基础版】打卡第5天:第26~30题⛅前言超过5名学生的课🔒题目🔑题解 求关注者的数量🔒题目🔑题解 只出现一次的最大数字🔒题目🔑题解 买下所有产品的客户&#x1f…

vue踩的坑:属性报undefined错误问题汇总

问题 在一个组件里&#xff0c;通过props传值进去对象&#xff0c;在控制台打印报错误信息&#xff0c;提示某属性不存在。 例如&#xff1a; <div>{{data.param.aaa}}</div> 类似这种的&#xff0c;取对象子级下面的值&#xff0c;就报了undefined。 原因应该…

机器学习(21)---召回率(recall)、精度(precision)和准确率(accuracy)

文章目录 1. 分布不平衡的数据集2. TP、TN 、FP 、FN3. 混淆矩阵4. 各自的计算公式5. 例题应用 1. 分布不平衡的数据集 1. 精度&#xff08;precision&#xff09;和召回率&#xff08;recall&#xff09;是衡量机器学习模型性能的重要指标&#xff0c;特别是数据集分布不平衡的…

Ubuntu 20.04LTS环境下替换Vivado 2019.2代码编辑器

Ubuntu使用 打开 tools-settings-Text Editor 参考 打开 tools-settings-Text Editor 选中Custom Editor&#xff0c;然后点击右边的三个点&#xff0c;弹出这个界面 然后切换到linux 终端&#xff0c;安装xterm 然后在下面编辑框里输入&#xff1a; xterm -geometry 100x60 …

苹果电脑用什么清理软件比较好?

很多人都会有这样的误解&#xff1a;mac系统不用清理。实际上mac只是将系统垃圾隐藏了&#xff0c;并且需要通过特定的方式打开。但其实在我们日常工作不用这么麻烦&#xff0c;我们只需用苹果电脑专业的清理软件就好了。今天小编就给大家分享一下mac用什么清理软件好 一、mac用…

nvm: node版本管理工具

有时候需要新旧项目一起开发&#xff0c;但是旧的项目用的node版本比较低&#xff0c;也不好升级&#xff0c;所以我们可以使用nvm 来进行node版本管理 1. 准备工作 先删除掉原来的nodejs 下载nvm: 官网地址&#xff1a;Releases coreybutler/nvm-windows GitHub 百度网盘…

Apollo版本变迁里程碑:从诞生到巅峰的无人驾驶之路

特点与改进 概述里程碑版本变迁6.0特点及改进7.0特点及改进8.0特点及改进代码差异 福利活动 主页传送门&#xff1a;&#x1f4c0; 传送 概述 Apollo (阿波罗)是一个开放的、完整的、安全的平台&#xff0c;将帮助汽车行业及自动驾驶领域的合作伙伴结合车辆和硬件系统&#xf…

为啥 Erlang 没有像 Go、Scala 语言那样崛起?

为啥 Erlang 没有像 Go、Scala 语言那样崛起&#xff1f; - 知乎 问&#xff1a; 成熟的杀手级产品&#xff0c;技术栈完整&#xff0c;社区活跃&#xff0c;易上手使用的人比较多。 scala 目前业界应用广泛&#xff0c;技术栈完整&#xff0c;社区活跃&#xff0c;还有 spar…

Bun v1.0.3 发布,Zig 编写的 JavaScript 运行时

导读Bun 发布了其最新版本 v1.0.3&#xff0c;这是一个集 JavaScript 运行时、打包器、转译器和包管理器于一体的工具。这次的更新不仅修复了众多已知的问题&#xff0c;还引入了一系列令人期待的新功能。 首先&#xff0c;Bun 在这个版本中增加了对 TypeScript 的 emitDecora…