从架构层面分析接口性能优化

2025博客之星年度评选已开启 10w+人浏览 2.6k人参与

从架构层面分析接口性能优化

  通过这篇文章你将了解到接口性能优化相关的知识,包括客户端/前端优化、网络传输优化、服务端优化、数据库优化、架构与部署优化等方面。


—— 2025 年 12 月 7 日 乙巳蛇年十月十八 大雪
扫码关注微信公众号   了解最新最全文章

qrcode

前言

  性能是软件系统最重要的非功能性需求之一,它是指系统的响应能力,即要经过多长时间才能对某个事件做出响应,或者在一定时间段内所能处理的事件的个数。而接口响应速度是日常开发活动中最常见的性能要求之一,接口性能优化是一个系统性的工程,从一个接口工作的整个流程出发,可能会涉及到客户端/前端、网络传输、后端服务、数据库以及系统架构等多个层面,所以在优化时需要从这些层面进行综合考虑。

1 客户端/前端优化

1.1 减少请求次数

  • 合并请求:指将多个小的请求合并为一个大请求,合并请求的本质是减少 http 操作,实际上大部分情况下接口耗时大多都在 io 操作上,所以合并请求在减少客户端/前端请求次数的情况下,又能降低服务端资源开销,从而能在极大程度上提高系统性能。
  • 资源合并:这里的资源合并是指合并 css、js 等静态资源。

1.2 缩小请求数据量

  • 数据压缩:指通过 gzip 等技术压缩要在网络中传输的数据量,从而提高传输效率,尤其是对文本数据而言,其压缩率可达 70% 以上。实际上数据压缩不仅可以在客户端和服务端做,还可以在网关或代理层做,比如如果你的项目使用了 nginx 反向代理,那么建议在 nginx 层面进行数据压缩,因为这样更高效,且方便统一管理。
  • 精简结果:指移除传输的数据结构(如 json)中不必要的字段,并采用简单且含义明确的属性名。做过的都知道,其实这是个吃力不讨好的活,有时候可能同一批数据要提供给多个需求方,总不能每个需求方都定义一个数据结构吧。但秉持着专业负责的工作态度,为了那 0.01% 性能,也就认了!
  • 数据分页:分页的目的是为了避免在大数据量情况下,传输的数据太多而导致接口响应时间过长的现象,尤其是在列表、表格或滚动场景中,属于基操。
  • 懒加载:指需要真正展示数据时采取加载数据,比如图片、视频及文件等媒体数据,当然数据分页本质上也属于懒加载思想。

1.3 利用缓存

  • http 缓存:可合理设置 Cache-ControlETagLast-Modified 头,利用浏览器缓存。
  • 本地缓存:可通过 LocalSrorageSessionStorage 等技术缓存更新频率较低的数据,如用户信息、权限信息等。

2 网络传输优化

  网络传输优化可通过 CDN 加速、数据压缩和精简结果等方案实现。

  • CDN 加速:将 css、js、图片、字体等静态资源部署到 CDN,利用边缘节点加速。其本质是将资源缓存在多个不同地理位置的服务器上,用户访问时让用户从地理位置上最近的服务器获取数据,从而通过大幅减少数据传输时间来加速数据的加载速度。
  • 数据压缩:和前面提到的数据压缩同理,本质是通过降低传输在网络中的数据体积来减少传输时间。
  • 精简结果:既然传输的数据过大会增加传输时间,那么我们则可以通过精简结果来缩小数据体积,从源头上消灭它。

3 服务端优化

3.1 缓存策略

  缓存策略是提高系统性能的最有效手段。缓存策略的本质是空间换时间,缓存的特点是访问速度快,并发高。我们把一些访问频繁且更新频率较低的热点数据提前放入缓存中,以此减少数据库的访问次数,同时,有些数据是来自多个数据源并根据业务逻辑计算而来的,缓存的存在也一定程度上避免了数据的重新计算而带来的开销。

  当然,缓存是一把双刃剑,需要合理使用,尤其是数据一致性方面,不过在大多数场景下都是提升系统性能的最佳方案。

  设计缓存策略时需要注意以下几点:

  • 多级缓存:缓存并非单一存在,比如 CPU 缓存就设计了三层。而这里的多次缓存是指我们在设计时可以针对 浏览器缓存 -> CDN 缓存 -> 反向代理缓存 -> 应用内存缓存(Caffeine) -> 分布式缓存(redis) 这些层级进行缓存。

  • 缓存数据:缓存的数据尽量对象化,即它是符合业务逻辑要求或需求方要求的,是经过加工处理的,而非数据库表中的原始数据。

  • 缓存更新策略:为了保证数据的实时性,缓存的数据是需要随着数据库数据的变化而及时更新的,常见的缓存更新策略包括 Cache-AsideRead/Write ThroughWrite Behind 等模式,但在实际应用中通常选择 Cache-Aside 模式。

      Cache-Aside 模式采用懒加载的思想。访问数据时先访问缓存,若命中则返回,若未命中则访问数据库,然后构建缓存数据并将其写入缓存,最后响应请求;更新数据时先更新数据库,然后使相关缓存失效,待下一次缓存被访问时再重新构建。

  • 缓存过期策略:缓存资源是非常珍贵的,缓存之所以能够快速访问是因为大多数缓存都是基于内存实现,所以为了不浪费或占用缓存空间,在使用缓存时需要设置合理的过期策略。比如缓存届的明星 redis,其采用 定期删除 + 惰性删除 + 内存淘汰机制 的策略:

    • 定期删除:指 redis 默认会每隔 100ms 随机抽取一些设置了过期时间的 key,检查其是否已过期,若已过期则将其删除。定时删除会造成没有设置过期时间且但实际上该缓存数据已经过期或设置了过期时间但已经过期的 key 依旧存在,于是就有了惰性删除。
    • 惰性删除:指当客户端访问某个 key 时,redis 会先检查其是否设置了过期时间,若设置了则再检查是否已过期,若已过期则直接删除并返回空。惰性删除会造成长时间不被使用且已过期的 key 依旧存在,于是就有了内存淘汰机制。
    • 内存淘汰机制:redis 提供了八种内存淘汰机制,碍于篇幅原因,有兴趣的同学可自行了解。
  • 缓存常见问题:缓存常见问题有 缓存雪崩缓存穿透缓存击穿 等,这都老八股文了,关于这些问题的描述、解决方法以及 redis 相关八股文大家可访问之前写的一篇文章 走近科学之 Redis 的秘密

3.2 异步与非阻塞

  • 异步处理:对于耗时且业务上允许异步的操作(如批处理、消息推送、复杂业务计算、邮件发送等),可以使用消息队列、定时任务等异步操作进行解耦,避免客户端长时间等待。
  • 非阻塞 IO:可使用 NIO、Netty 等异步 IO,以提高线程利用率和并发能力。

3.3 代码与逻辑优化

  • 算法优化:在涉及到算法相关的编码时,尽量使用或设计时间复杂度更低的算法。实际上在两全不能其美的情况下,更推荐用空时间换时间,即通过牺牲空间复杂度来保证时间复杂度,毕竟现在内存也没那么贵。
  • 减少计算开销:避免在循环中进行重复耗时的操作(如数据库访问、复杂计算、IO 操作等),这都老生常谈的话题了,但却容易被忽略。
  • 提前过滤:今早进行数据验证和过滤,避免无效请求穿透到下游。
  • 池化技术:使用线程池、对象池、数据库连接池等技术,避免重复创建和销毁所带来的开销。

3.4 串行改并行

  将一个请求内的多个不相互依赖的任务并行执行,从而缩短整体执行时间。这些任务可以是复杂计算、数据访问、IO 操作、远程调用等,总之只要它在业务上或逻辑上可并行执行,那就可以由串行改并行。

3.5 避免大事务

  大事务是指运行时间过长的事务,它可能涉及多个数据库操作,也可能是涉及的数据量过大。大事务会长时间持有锁,影响系统性能;也可能由于锁定多行记录从而导致其他请求等待,进而影响其它接口性能;提交和回滚时间也会增大。总之,我们可以从业务逻辑、结构设计等方面着手,尽量避免大事务。

4 数据库优化

  实际上数据库设计才是对整个系统扩展、优化影响最大的一环,同时也是系统设计的重中之重。相信有经历的同学一定会有这样的感触,那些奇怪的设计简直让人抓狂。如果你的项目使用的是 mysql 或你正计划学习 mysql 相关的知识,那么我之前写过一篇关于 mysql 的文章 走近科学之 MySQL 的秘密 以及关于 sql 的文章 禁奥义·SQL秘籍:关于 SQL 的这些知识 你学会了吗 ,你可以看看,或许会对你有所帮助。

4.1 数据库设计

  • 表设计:合理的字段长度、字段类型,合理的列数,创建合理的索引,适当的反规范化设计(如增加冗余列、增加派生列、表重组、表分割等)等。
  • 读写分离:主写从读,多主写多从读等。
  • 分库分表:水平分、垂直分、混合分等。
  • 合适的数据库:如适用于强一致性、复杂查询、事务处理的关系型数据库;适用于高并发写入、大数据场景的 NoSQL 数据库;适用于多对多关系分析、社交网络查询的图数据库等。

4.2 SQL 优化

  • 避免 select *、全表扫描、大表 join 等。
  • 使用批量操作,如 insert into ... values (), (), ()mybatis <foreach> 等,减少 io 操作。
  • 使用 explain 分析 sql 执行计划,以合理设计和优化 sql
  • 使用慢 sql 查询日志,定期分析并优化慢 sql

4.3 索引优化

  • 确保查询有效利用所有。
  • 避免索引失效,如 !=、<、>、in 等操作。
  • 覆盖索引,索引包含所有查询字段,避免回表。
  • 注意索引最左前缀原则。

5 架构与部署优化

  系统架构设计贯穿整个软件生命周期,不同特点的架构将对软件的发展产生深远影响,比如你的数据库系统支不支持水平扩展,会不会出现数据冲突或不一致的情况;你的服务是不是无状态的,支不支持多节点部署,会不会出现并发问题;你的缓存支不支持水平扩展,有没有解决常见缓存问题,缓存更新策略又如何;你的系统有没有平衡流量,有没有负载均衡,有没有限流降级容错,有没有高可用策略等等。

  一个大型网站的系统架构演化可能会经历以下过程:

  • 1、单体架构:刚开始,业务小,日活低,可能一个服务就可以,甚至应用服务、数据库、文件等都部署在同一台服务器上也是可以的。
  • 2、垂直架构:慢慢的,随着业务数据的增长,可能会将数据库放在单独的服务器上,将文件也放在单独的服务器上。
  • 3、引入缓存:随着用户的增长,系统的性能有所下降,所以你用最直接最有效的缓存技术来解决,方便高效。
  • 4、集群与负载均衡:然而受限于服务器的配置,服务的并发能力又成了系统的性能瓶颈,所以你采用集群部署与负载均衡的策略,提升服务并发能力的同时又合理利用了现有资源。
  • 5、读写分离:没错儿,是水桶效应,数据库又成了系统性能瓶颈。但没关系,这时候你已经是一个合格的程序员了,你采用读写分离、主写从读的策略,完美解决了问题。
  • 6、CDN 加速:业务蒸蒸日上,客户遍布全国,你用 CDN 加速来突破数据传输与地域边界,使内容传输的更快,更稳定。
  • 7、分布式数据库系统与分布式文件系统:业务的快速增长带来了庞大的业务数据,这时候你决定采用分布式数据库和分布式文件系统,高可用、高性能、高并发都满足。
  • 8、NoSQL与搜索引擎:大型系统常面临着海量数据的快速查询需求,所以你引入了搜索引擎与NoSQL数据库,其高性能、可扩展性和灵活性完美支撑了你的需求。
  • 9、分布式服务:业务是在太庞大了,你必须进行业务拆分,分而治之,什么微服务、注册/发现、服务网关、远程调用、限流熔断、分布式事务等这些技术也上了。系统逐渐稳定,鉴于你丰富的工作经验,扎实的技术能力,公司决定将你输送到社会上,让你继续发光发热。

  所以你看,系统的演化本质上是性能需求驱动的。

  所以,系统架构设计是整个软件生命周期中最重要的一环,它是系统的上限,是系统的基石,毕竟万丈高楼从地起。如果你是团队中的架构师,或者你经常从事于架构设计相关的工作,那么你一定要考虑这些问题,否则将会成为自己的枷锁,当然如果你有着 代码和人有一个能跑就行了 的觉悟,那么,对吧。

qrcode

扫码关注微信公众号   了解最新最全文章
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红衣女妖仙

行行好,给点吃的吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值