1. 这道面试题到底在问什么
提到“京东一面:接口性能优化,有哪些经验和手段”,很多人第一反应是赶紧背一堆名词——Redis缓存、异步消息、分库分表、索引优化,然后一股脑往外倒。我自己在面试候选人的时候,见过太多这种答法:名词说了一大堆,每个都蜻蜓点水,问他“缓存穿透和缓存击穿的区别是什么”能说清,再问“你线上接口RT从500ms降到150ms,具体是怎么定位瓶颈的”就卡壳了。
这个标题真正想考察的,不是你能不能列举优化手段,而是你有没有一套完整的性能优化方法论。什么算完整?至少包含三件事:第一,你知道从哪里开始排查,而不是上来就加缓存;第二,你清楚每种手段的适用范围和代价,知道什么时候该用什么时候不该用;第三,你踩过坑,知道哪些方案看起来很美但实际上线容易出问题。
所以这篇文章我不打算给你列一个“优化手段清单”就完事,而是按我自己在真实项目里推进性能优化的顺序,一步步拆解:先讲怎么建立指标体系和定位瓶颈,再讲业务层最常动手的几个方向,接着是数据和存储层的关键优化,最后是那些容易翻车的细节和排查经验。整套走下来,你既能在面试时讲出层次感,也能在真实项目里直接落地。
我默认看这篇文章的你至少写过几年业务代码,知道接口大概是怎么跑通的。如果你还是在校生或者刚转行,也别慌,我会把每个环节涉及的基础概念顺手解释清楚,只是不会花大篇幅去讲什么是HTTP、什么是数据库这种最底层的东西。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 第一步不是优化,是先建立优化目标和瓶颈定位
2.1 没有指标体系的优化全是“拍脑袋”
很多团队做性能优化的方式是这样的:线上某个接口变慢了,老板说“你优化一下”,然后开发同学打开代码,凭感觉觉得“这里好像能加个缓存”“那里好像能改个SQL”,改完上线,RT确实降了一点,但没人说得清到底降了多少、为什么降、稳定性有没有受影响。
这属于典型的没有指标体系就开始动手。正确做法是先把指标定义清楚,让优化这件事变得可测量。接口性能优化里最基础也最常用的三个指标:
- RT(Response Time,响应时间):从客户端发出请求到收到完整响应的时间,通常看平均值、TP99、TP999这几个分位数。平均值容易被极端值拉偏,所以线上监控主要看分位数。
- QPS(每秒请求数):接口每秒能处理的请求量。RT和QPS是一对矛盾体,RT降下来往往意味着QPS能上去,但系统资源有限,QPS压到极限RT也会恶化。
- 错误率:5xx、超时、业务异常占总请求量的比例。优化过程中如果错误率上升,那说明优化方向有问题。
我有一次接手一个老系统的订单查询接口,RT平均在800ms左右,看着确实慢。但等我把监控搭好、观察了一周数据后发现,TP99高达2.3秒,可TP50只有200ms。这说明绝大多数请求很快,只有一小部分请求特别慢,把平均值拉高了。这时候最优的优化方向根本不是“整体加缓存”,而是去查那部分慢请求到底什么原因——后来发现是某些大客户订单量特别大,查询时深分页扫了大量数据。
如果一开始不看分位数,直接把缓存加在整个接口上,那部分慢请求大概率还是慢,因为深分页的数据根本不会被缓存命中。
2.2 定位瓶颈的顺序:链路追踪、日志、监控三板斧
指标建立好之后,接下来要回答一个问题:这800ms到底消耗在哪了?是网络传输、Web容器线程排队、业务代码计算、数据库查询,还是下游RPC调用?
靠猜肯定不行,需要工具支撑。我建议至少把下面三层基础能力建好,这不仅是性能优化的前提,也是日常排查线上问题的底子:
- 全链路追踪:用Trace ID贯穿整个请求链路,可以清楚看到一次请求在网关、各个微服务之间分别耗时多少。市面上常用的是SkyWalking、Zipkin或者公司自研的APM系统。哪怕项目再小,也建议引入一个轻量级的方案,至少做到服务间调用耗时可见。
- 应用层监控:JVM的GC频率和耗时、线程池活跃线程数、Tomcat连接池状态等。我见过很多接口变慢其实是GC停顿或者连接池被占满导致的,而不是业务代码本身有问题。
- 数据库监控:慢SQL日志、数据库连接数、锁等待时间、索引命中情况。MySQL的慢查询日志一定要开,阈值先设1秒,后续根据情况再调。
这套排查逻辑放到面试里也很好用:当面试官问“如果一个接口很慢,你怎么排查”,你把从全链路追踪看调用耗时分布,到定位某个环节的慢SQL,再到通过日志确认数据特征,最后决定优化方案这条路径讲清楚,就已经比90%的候选人有逻辑了。
2.3 技术选型不是越高级越好,要匹配团队维护能力
定位到瓶颈之后才是选方案。这里提个很多人忽略的点:性能优化方案的技术选型,一定要考虑团队的维护能力。
举个最常见的例子,本地缓存。Caffeine、Guava Cache这些都是成熟方案,性能也很好。但如果不考虑数据一致性问题就盲目上,线上会出现用户改了昵称,接口还返回旧昵称的尴尬情况。这时候你就要做缓存过期策略、主动失效、版本号控制这些设计。
再比如消息队列解耦,Kafka吞吐量确实高,但引入Kafka意味着你要处理消息丢失、重复消费、顺序性、消费堆积等一系列问题。如果团队里没人真正熟悉Kafka的运维和调优,我宁可先用一个简单的线程池异步化把问题解决了,等业务量真到了需要上消息队列的规模再引入也不迟。
性能优化本质上是技术债务的偿还,但引入新的技术组件同时也在积累新的债务。每一次选型都要算清楚这笔账。
3. 业务层性能优化:缓存、异步和并发这“三驾马车”
3.1 缓存优先,但要先搞清楚穿透、击穿、雪崩
缓存是接口性能优化里见效最快的手段,没有之一。但很多人对缓存的理解停留在“加一层Redis”,上线之后被穿透、击穿、雪崩折磨得死去活来。
先看三者的区别,用生活里的场景类比一下就很好记:
- 缓存穿透:查一个根本不存在的数据,比如
