高并发性能调优是一项系统化工程,需要从“度量 → 定位 → 优化 → 验证”四个关键环节入手,形成闭环管理。
本文整理了一份实战导向的“高并发性能调优作战清单 + 面试速答模版”,不仅覆盖全流程技术要点,还提供可直接复述的表达框架,帮助你在实际工作中从容应对性能瓶颈,也能在面试现场条理清晰地展现专业能力。
无论是排查线上问题还是准备技术面试,这份清单都能成为你的高效工具。接下来,我们将逐一拆解每个环节的核心策略与操作要点,助你快速掌握高并发调优的完整打法。
一、度量与定位(先量化,再下手)
- 核心指标(Golden Signals):RPS/QPS、P95/P99 延迟、错误率、饱和度(CPU/堆/连接/线程池队列)。
- 可观测性:应用指标(Micrometer/Prometheus + Grafana)、链路追踪(OpenTelemetry/Jaeger)、日志(结构化 + 采样)。
- 采样/画像:JFR/async-profiler/Arthas/Flame Graph 定位热点;
top/iostat/vmstat/nmon
看系统瓶颈;压测(JMeter/k6)重现问题。 - 先判性质:CPU 绑死(算力)/GC 频繁(内存)/慢 SQL(IO)/锁竞争(并发)/外部依赖(下游)/网络(带宽/RTT)。
我们首先详细解释“度量与定位”环节中的每一个核心指标与技术手段,帮助你系统化掌握高并发性能调优的第一步:先量化问题,再精准下手。
1.1 核心指标(Golden Signals)
1. RPS/QPS(每秒请求数)
含义:衡量系统单位时间内处理的请求数量,是评估系统吞吐能力的最直接指标。
应用场景:
-
压测时观察系统处理能力的上限;
-
线上监控流量突增或下降;
-
评估扩容或缩容策略是否有效。
工具:通常通过 Prometheus + Grafana 进行实时监控。
2. P95/P99 延迟(响应时间)
含义:
- P95 表示 95% 的请求响应时间小于该值;
- P99 表示 99% 的请求响应时间小于该值。
这是衡量用户体验的关键指标,比平均延迟更能反映系统“长尾”问题。
应用场景:
- 判断是否存在慢请求;
- 优化后验证延迟是否改善。
工具:Micrometer、Prometheus、APM 工具(如 SkyWalking)。
3. 错误率
含义:请求处理失败的比例,通常包括 HTTP 5xx、业务异常、超时等。
应用场景:
- 判断系统稳定性;
- 识别异常流量或依赖故障。
工具:日志系统(如 ELK)、APM 工具、Prometheus Alertmanager。
4. 饱和度(资源使用率)
含义:衡量系统资源的使用紧张程度,包括:
- CPU 使用率:高 CPU 可能意味着计算密集型任务或死循环;
- 堆内存使用:频繁 GC 或 OOM 风险;
- 连接数/线程池队列:线程阻塞或连接泄漏;
- 磁盘/网络 IO:慢查询或带宽瓶颈。
应用场景:
- 判断是否需要扩容;
- 定位资源瓶颈。
工具:top
、vmstat
、iostat
、nmon
、JConsole/VisualVM。
1.2 可观测性
1. 应用指标(Micrometer/Prometheus + Grafana)
作用:实时采集应用指标(如 QPS、延迟、错误率),并通过 Grafana 可视化展示。
优势:
- 支持多语言、多框架;
- 灵活的告警规则;
- 易于集成 CI/CD 流程。
2. 链路追踪(OpenTelemetry/Jaeger)
作用:追踪请求在分布式系统中的完整调用链,帮助定位慢调用或依赖异常。
优势:
- 支持跨服务追踪;
- 可视化调用拓扑;
- 结合指标和日志进行根因分析。
3. 日志(结构化 + 采样)
作用:通过结构化日志(如 JSON 格式)记录关键事件,便于查询和分析。
优化建议:
- 采用日志采样减少存储压力;
- 使用集中式日志系统(如 ELK、Loki);
- 打印 TraceID 以便关联链路追踪。
1.3 采样与画像技术
1. JFR(Java Flight Recorder)
作用:JDK 内置的低开销事件记录工具,可用于分析 JVM 性能问题。
适用场景:
- GC 频繁;
- 方法调用耗时异常。
2. async-profiler
作用:生成 CPU 火焰图,快速定位 CPU 密集型代码热点。
优势:
- 低开销;
- 支持多种事件类型(CPU、内存、锁等)。
3. Arthas
作用:在线诊断工具,支持动态查看方法调用、变量值、线程状态等。
常用命令:
trace
跟踪方法调用;watch
观察方法返回值;thread
查看线程堆栈。
4. Flame Graph(火焰图)
作用:可视化 CPU 调用栈,直观展示热点函数。
使用场景:
- 定位性能瓶颈函数;
- 优化代码路径。
5. 系统监控工具
常用命令:
top
:查看 CPU 和内存使用情况;vmstat
:监控系统进程、内存、IO;iostat
:查看磁盘 IO;nmon
:综合性能监控工具。
6. 压测(JMeter/k6)
作用:模拟高并发场景,重现性能问题。
建议:
- 逐步加压,观察拐点;
- 结合监控工具分析瓶颈。
1.3 先判性质(问题分类)
1. CPU 绑死
表现:CPU 使用率持续 100%。
可能原因:
- 死循环;
- 计算密集型任务;
- JIT 编译。
排查方法:top
+ async-profiler
。
2. GC 频繁
表现:频繁 Full GC 或 Young GC,应用暂停。
可能原因:
- 内存泄漏;
- 对象创建过多。
排查方法:GC 日志 + 堆转储(Heap Dump)。
3. 慢 SQL
表现:数据库查询响应慢。
可能原因:
- 缺少索引;
- SQL 写法不佳;
- 数据库压力大。
排查方法:慢查询日志 + EXPLAIN
。
4. 锁竞争
表现:线程阻塞,吞吐量下降。
可能原因:
- 同步块过多;
- 锁粒度过大。
排查方法:jstack
分析线程状态。
5. 外部依赖
表现:调用下游服务超时或失败率高。
可能原因:
- 下游服务不稳定;
- 网络抖动。
排查方法:链路追踪 + 熔断降级策略。
6. 网络
表现:请求响应慢或失败。
可能原因:
- 带宽不足;
- RTT(Round Trip Time)过高。
排查方法:ping
、traceroute
、mtr
。
1.5 小结
“度量与定位”是高并发性能调优的基础,必须通过系统化手段量化问题,再结合可观测性工具和画像技术,精准判断瓶颈类型。掌握这些核心指标和工具,不仅能提升线上问题排查效率,也能在面试中展现系统化的技术思维。接下来,我们将进入“优化”环节,针对不同类型的问题给出具体的优化策略。
二、应用层优化(Java/JVM/并发)
- 线程池:按场景分池;限队列长度;拒绝策略兜底;大小估算≈
Ncpu * Ucpu * (1 + W/C)
。 - 异步/背压:CompletableFuture/Reactor;限流(令牌桶/滑动窗口);舱壁隔离 + 熔断(Resilience4j)。
- 锁与对象:减少共享、用无锁/分段锁、降低锁粒度;避免大对象/频繁装箱;复用编解码缓冲。
- JVM/GC:G1/ZGC;固定堆
-Xms = -Xmx
;合理-XX:MaxGCPauseMillis
;降 Young Gen 晋升;避免频繁 Full GC。 - 序列化:JSON→二进制(Kryo/Protostuff/ProtoBuf),减少字段;HTTP→gRPC(服务内)。
2.1 线程池优化
接下来,我们详细拆解“应用层优化(Java/JVM/并发)”部分的每一条策略,帮助你掌握高并发场景下的代码与 JVM 层调优技巧,提升系统吞吐能力与稳定性。
1. 按场景分池
含义:不同业务场景使用独立的线程池,避免资源竞争。
场景示例:
- I/O 密集型任务(如 HTTP 调用);
- 计算密集型任务(如数据处理);
- 定时任务调度。
优势:隔离不同任务的资源使用,防止某一类任务拖垮整个系统。
2. 限队列长度
含义:控制线程池任务队列的最大长度,避免任务堆积导致内存溢出。
建议值:根据系统资源与业务容忍度设定,通常为几十到几百。
配置示例:
new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(100) // 限制队列长度
);
3. 拒绝策略兜底
含义:当线程池与队列都满时,采用合理的拒绝策略,避免系统崩溃。
常见策略:
AbortPolicy
(默认):抛出异常;CallerRunsPolicy
:由调用线程执行;DiscardPolicy
:直接丢弃;DiscardOldestPolicy
:丢弃队列中最旧的任务。
推荐:根据业务重要性选择,如日志服务可丢弃,核心服务降级处理。
4. 线程池大小估算
公式:
线程数 ≈ Ncpu * Ucpu * (1 + W/C)
Ncpu
:CPU 核心数;Ucpu
:期望 CPU 利用率(0~1);W/C
:等待时间与计算时间比值。
示例:8 核 CPU,目标利用率 80%,W/C=1,则线程数 ≈ 12。
2.2 异步与背压
1. 异步编程
技术选型:
CompletableFuture
:适合简单异步任务编排;Reactor
(Project Reactor):适合响应式流处理。
优势:避免线程阻塞,提升吞吐量。
2. 限流策略
令牌桶算法:匀速发放令牌,突发流量可短暂通过。
滑动窗口:精确控制单位时间内的请求量。
工具:Guava RateLimiter、Sentinel、Resilience4j。
3. 舱壁隔离 + 熔断
舱壁隔离:为不同服务或模块分配独立资源池,避免雪崩。
熔断机制:当失败率或延迟超过阈值时,自动降级或熔断。
推荐工具:Resilience4j、Hystrix(逐渐被 Resilience4j 替代)。
2.3 锁与对象优化
1. 减少共享
策略:尽量使用线程局部变量(ThreadLocal
)或不可变对象,减少锁竞争。
示例:日期格式化工具类用 ThreadLocal
缓存实例。
2. 无锁/分段锁
无锁结构:Atomic
类、ConcurrentHashMap
。
分段锁:如 ConcurrentHashMap
的分段锁机制(JDK8 后改为 CAS + synchronized)。
优势:减少锁粒度,提升并发性能。
3. 避免大对象/频繁装箱
大对象:如大数组、大 Map,容易造成 Full GC。
频繁装箱:如 int
和 Integer
转换,增加 GC 压力。
建议:
- 使用基本类型;
- 拆分大对象;
- 复用对象(如对象池)。
4. 复用编解码缓冲
场景:网络通信、序列化/反序列化频繁分配缓冲区。
优化:使用 ByteBuffer
池或 Netty
的 ByteBuf
池,减少 GC 压力。
2.4 JVM 与 GC 调优
1. 垃圾收集器选择
- G1:适合大堆内存(>4GB)、低延迟;
- ZGC:超大堆(TB 级别)、超低延迟(<10ms);
- CMS(已废弃):不建议使用。
推荐:JDK9+ 默认 G1,超低延迟场景选 ZGC。
2. 固定堆大小
配置:-Xms = -Xmx
,避免堆动态扩容带来的性能抖动。
示例:
-Xms4g -Xmx4g
3. 合理设置 GC 停顿目标
G1 参数:
-XX:MaxGCPauseMillis=200
说明:G1 会尽量调整参数满足停顿时间目标,但不绝对保证。
4. 降低 Young Gen 晋升
策略:
- 增大 Young Gen 区大小;
- 减少对象生命周期;
- 避免长期持有对象引用。
目的:减少对象晋升到 Old Gen,降低 Full GC 频率。
5. 避免频繁 Full GC
手段:
- 优化内存使用,减少大对象;
- 检查内存泄漏;
- 合理设置 GC 参数(如
XX:InitiatingHeapOccupancyPercent
)。
2.5 序列化优化
1. JSON → 二进制
原因:JSON 解析慢、体积大,不适合高吞吐场景。
推荐:
- Kryo:高效、易集成;
- Protostuff:基于 Protobuf,无需 .proto 文件;
- ProtoBuf:跨语言支持强,适合微服务。
优化建议:减少序列化字段,使用transient
或@JsonIgnore
。
2. HTTP → gRPC
优势:
- 基于 HTTP/2,多路复用;
- 使用 Protobuf 序列化,性能更高;
- 支持流式通信。
适用场景:服务内部调用、高并发微服务架构。
2.6 小结
应用层优化是高并发性能调优的核心环节,涵盖线程池、异步编程、锁优化、JVM 调优和序列化等多个方面。通过合理配置线程池、引入异步与背压机制、优化锁策略、选择合适的 GC 算法以及改用高效序列化方式,可以显著提升系统的吞吐能力与稳定性。
三、数据层(MySQL/Redis/索引/分页)
- MySQL
- 索引:覆盖索引、最左前缀、避免函数列;
EXPLAIN
+ 慢日志(pt-query-digest)。- 语句:避免
SELECT *
、N+1、OR 过多;批量写(batch/多值插入);可靠分页(id > ? limit ?
)。 - 结构:冷热分离、读写分离、分库分表(按业务主键/时间);事务短小、降低隔离级别。
- 连接池:Hikari 固定上限,PreparedStatement 缓存。
- 语句:避免
- Redis
- 缓存模式:Cache Aside;避免大 Key;TTL + 随机抖动。
- 热点:本地缓存 + 二级缓存、布隆过滤(穿透)、互斥锁/逻辑过期(击穿)、分批重建(雪崩)。
- 原子性:Lua/事务管道;频繁计数用 HyperLogLog/bitmap;限流用滑动窗口脚本。
- 网络:pipeline 批量;合理连接数;禁用 KEYS/SCAN 大范围在生产热路径。
接下来,我们详细拆解“数据层优化(MySQL/Redis/索引/分页)”部分的每一条策略,帮助你掌握高并发场景下数据库与缓存层的调优技巧,提升数据访问效率与系统稳定性。
3.1 MySQL 优化
1. 索引优化
覆盖索引
含义:查询字段全部包含在索引中,避免回表。
示例:
CREATE INDEX idx_name_age ON user(name, age);
SELECT name, age FROM user WHERE name = '张三';
优势:减少 I/O,提升查询速度。
最左前缀原则
含义:复合索引按最左侧字段匹配。
示例:
-- 索引 (a, b, c)
WHERE a = 1 AND b = 2; -- 可用
WHERE b = 2 AND a = 1; -- 可用(优化器会调整顺序)
WHERE b = 2; -- 不可用
建议:将高频查询字段放在索引最左侧。
避免在索引列上使用函数
示例:
-- 不可用索引
SELECT * FROM user WHERE YEAR(create_time) = 2023;
-- 改为范围查询
SELECT * FROM user WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01';
使用 EXPLAIN
+ 慢日志分析
EXPLAIN
查看执行计划,判断是否走索引;- 慢日志(
slow_query_log
)记录执行时间长的 SQL; - 使用
pt-query-digest
工具分析慢日志,定位热点 SQL。
2. SQL 语句优化
避免 SELECT *
原因:增加 I/O 和网络传输;
建议:只查询必要字段。
避免 N+1 查询
问题:循环查询数据库,如:
for (User user : users) {
List<Order> orders = orderDao.getByUserId(user.getId());
}
优化:使用 IN
或 JOIN
一次性查询。
避免 OR
过多
问题:OR
会导致索引失效。
优化:使用 UNION ALL
或拆分为多个查询。
批量写入(batch/多值插入)
示例:
INSERT INTO user (name, age) VALUES ('张三', 20), ('李四', 21);
优势:减少网络开销和事务提交次数。
可靠分页(避免深分页)
问题:
SELECT * FROM user ORDER BY id LIMIT 1000000, 10;
优化:基于 ID 或时间范围分页:
SELECT * FROM user WHERE id > 1000000 LIMIT 10;
3. 表结构优化
冷热分离
策略:
- 热数据(近期活跃)放高速存储(如 SSD);
- 冷数据(历史数据)归档或降级存储。
读写分离
架构:主库写,从库读。
工具:MySQL 主从复制、ProxySQL、ShardingSphere。
分库分表
策略:
- 按业务主键(如用户 ID);
- 按时间(如日志表按月分表)。
工具:ShardingSphere、MyCat。
事务短小 + 降低隔离级别
- 事务尽量短小,减少锁持有时间;
- 根据业务需求选择隔离级别(如
READ COMMITTED
)。
4. 连接池优化
使用 HikariCP
优势:高性能、轻量级。
配置建议:
spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 10
connection-timeout: 30000
PreparedStatement 缓存
作用:减少 SQL 解析开销。
配置:
spring:
datasource:
hikari:
cache-prep-stmts: true
prep-stmt-cache-size: 250
prep-stmt-cache-sql-limit: 2048
3.2 Redis 优化
1. 缓存模式
Cache Aside(旁路缓存)
流程:
- 先查缓存;
- 缓存未命中,查数据库;
- 写入缓存。
注意:更新时先更新数据库,再删除缓存。
避免大 Key
问题:大 Key 导致内存不均、网络阻塞。
优化:
- 拆分大 Hash/List;
- 使用
SCAN
替代KEYS
。
TTL + 随机抖动
策略:
- 设置合理的 TTL;
- 在 TTL 基础上增加随机值,避免缓存同时失效。
示例:
redis.setex(key, ttl + random(0, 300), value);
2. 热点 Key 处理
本地缓存 + 二级缓存
架构:
- 一级缓存(本地,如 Caffeine);
- 二级缓存(Redis)。
优势:减少 Redis 访问压力。
布隆过滤器(防止穿透)
场景:防止查询不存在的 Key。
工具:Guava BloomFilter、RedisBloom。
互斥锁/逻辑过期(防止击穿)
- 互斥锁:缓存失效时加锁,只允许一个线程重建缓存;
- 逻辑过期:缓存中存储过期时间,后台异步更新。
分批重建(防止雪崩)
策略:
- 缓存失效时分批重建;
- 设置不同的 TTL。
3. 原子性操作
Lua 脚本
优势:保证多个命令原子性。
示例:
if redis.call("GET", KEYS[1]) == false then
redis.call("SET", KEYS[1], ARGV[1])
return 1
else
return 0
end
频繁计数用 HyperLogLog/bitmap
- HyperLogLog:基数统计(如 UV);
- bitmap:状态标记(如签到)。
限流用滑动窗口脚本
示例:Lua 实现滑动窗口限流。
4. 网络优化
Pipeline 批量
作用:减少网络 RTT。
示例:
redis.pipelined(p -> {
p.set("key1", "value1");
p.set("key2", "value2");
});
合理连接数
配置:根据业务负载调整连接池大小(如 Lettuce 连接池)。
禁用 KEYS
/SCAN
大范围
问题:阻塞 Redis 线程。
替代:SCAN
分批查询,避免生产环境使用 KEYS
。
3.3 小结
数据层优化是高并发系统性能调优的关键环节,涵盖 MySQL 的索引、SQL、表结构、连接池优化,以及 Redis 的缓存模式、热点处理、原子性操作和网络优化。通过合理设计索引、优化 SQL 语句、使用缓存策略、避免热点 Key 和网络阻塞,可以显著提升数据访问效率,降低系统负载。
接下来,我们详细拆解“消息与解耦(MQ)”部分的每一条策略,帮助你掌握高并发场景下消息队列(MQ)的调优技巧,提升系统的解耦能力、削峰填谷效果与任务调度效率。
四、消息与解耦(MQ)
- 削峰填谷:生产限速,消费多分区并行;幂等(去重键/表、状态机)。
- 顺序与重试:关键流保持分区键一致;DLQ/重试退避;消息体瘦身(传引用)。
- 延迟任务:MQ 延迟等级/时间轮/Job 调度(避免 cron 洪峰)。
接下来,我们详细拆解“消息与解耦(MQ)”部分的每一条策略,帮助你掌握高并发场景下消息队列(MQ)的调优技巧,提升系统的解耦能力、削峰填谷效果与任务调度效率。
4.1 削峰填谷
1. 生产限速
含义:控制消息生产速率,避免瞬时流量压垮下游服务。
实现方式:
- 令牌桶算法(Guava RateLimiter);
- 滑动窗口限流(Sentinel);
- MQ 自带限流机制(如 RocketMQ 的生产流控)。
示例:
RateLimiter rateLimiter = RateLimiter.create(1000); // 每秒 1000 条
for (Message msg : messages) {
rateLimiter.acquire();
producer.send(msg);
}
2. 消费多分区并行
含义:通过分区(Partition)实现消息并行消费,提升吞吐量。
适用场景:Kafka、RocketMQ 等支持分区的 MQ。
优化建议:
- 分区数 ≥ 消费者数;
- 避免单分区消息倾斜(如按用户 ID 哈希分区)。
示例:
// Kafka 消费者组配置
props.put("partition.assignment.strategy", "org.apache.kafka.clients.consumer.RangeAssignor");
3. 幂等性设计
含义:确保重复消费不会导致业务异常。
实现方式:
- 去重键/表:如订单号 + 操作类型;
- 状态机:消息处理前检查当前状态,避免重复执行。
示例:
-- 去重表
INSERT INTO message_dedupe (msg_id, status) VALUES ('123', 'processed') ON CONFLICT DO NOTHING;
4.2 顺序与重试
1. 关键流保持分区键一致
含义:同一业务流的消息发送到同一分区,保证消费顺序。
适用场景:支付、订单等需要严格顺序的业务。
实现方式:
- Kafka 指定分区键;
- RocketMQ 使用顺序消息。
示例:
// Kafka 发送顺序消息
producer.send(new ProducerRecord<>("topic", "orderId", message));
2. DLQ(死信队列)与重试退避
DLQ 作用:存储多次重试失败的消息,避免阻塞主队列。
重试策略:
- 指数退避(如 1s、2s、4s、8s);
- 最大重试次数(如 3 次)。
示例:
// RocketMQ 配置 DLQ
consumer.setMaxReconsumeTimes(3);
consumer.setDelayLevelWhenNextConsume(3); // 退避等级
3. 消息体瘦身(传引用)
问题:大消息体(如 Base64 图片)占用网络和存储。
优化:
- 传引用(如文件 URL、数据库 ID);
- 压缩消息体(如 Gzip)。
示例:
{
"fileId": "12345",
"url": "https://cdn.example.com/file/12345"
}
4.3 延迟任务
1. MQ 延迟等级
适用场景:RocketMQ、RabbitMQ 支持延迟消息。
配置示例(RocketMQ):
Message msg = new Message("topic", "delay", body);
msg.setDelayTimeLevel(3); // 延迟 10s(等级对应时间可配置)
producer.send(msg);
2. 时间轮(Timing Wheel)
适用场景:高精度延迟任务(如 Kafka 内部使用时间轮管理超时)。
优势:
- 高效管理大量定时任务;
- 避免频繁扫描。
工具:Netty HashedWheelTimer。
3. Job 调度(避免 cron 洪峰)
问题:大量 cron 任务在同一时间执行导致洪峰。
优化:
- 分散调度时间(如加随机偏移);
- 使用分布式调度(如 Elastic-Job、XXL-JOB)。
示例:
// XXL-JOB 分片执行
@XxlJob("shardingJob")
public void shardingJob() {
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
// 按 shardIndex 处理分片数据
}
4.4 小结
消息队列(MQ)是高并发系统中实现解耦、削峰填谷和异步处理的核心组件。通过生产限速、消费并行、幂等设计、顺序保证、延迟任务调度等策略,可以显著提升系统的稳定性和吞吐能力。合理选择 MQ 类型(如 Kafka、RocketMQ、RabbitMQ)并结合业务场景优化配置,是构建高性能分布式系统的关键。
五、网关与网络/内核
- Nginx/服务网关:keepalive、
worker_connections
、server_tokens off
;HTTP/2;合并小响应。 - 内核参数:
somaxconn
、tcp_tw_reuse
、tcp_fin_timeout
、net.core.rmem_max/wmem_max
、ulimit -n
。 - 连接复用:HTTP 连接池、DNS 预热;跨 AZ/机房就近路由。
接下来,我们详细拆解“网关与网络/内核”部分的每一条策略,帮助你掌握高并发场景下网络层与系统内核的调优技巧,提升网关吞吐能力、网络传输效率与系统稳定性。
5.1 Nginx/服务网关优化
1. keepalive
长连接
含义:复用 TCP 连接,减少握手开销。
配置示例:
upstream backend {
server 10.0.0.1:8080;
keepalive 32; # 每个worker保持32个长连接
keepalive_timeout 60s;
keepalive_requests 1000;
}
适用场景:高并发短连接请求(如 API 网关)。
2. worker_connections
调整
含义:每个 Nginx worker 进程的最大连接数。
计算公式:
最大连接数 = worker_processes × worker_connections
配置示例:
worker_processes auto; # 自动根据CPU核心数设置
events {
worker_connections 4096; # 单worker处理4096个连接
}
3. 隐藏版本信息(server_tokens off
)
作用:减少信息泄露,提升安全性。
配置示例:
http {
server_tokens off;
}
4. 启用 HTTP/2
优势:
- 多路复用(减少 TCP 连接数);
- 头部压缩(HPACK);
- 服务器推送(可选)。
配置示例:
listen 443 ssl http2;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
5. 合并小响应
策略:
- 开启
gzip
压缩; - 使用
ngx_http_gzip_module
合并小文件; - 静态资源 CDN 预聚合。
配置示例:
gzip on;
gzip_min_length 1k;
gzip_types text/plain application/json;
5.2 内核参数调优
1. somaxconn
(TCP 监听队列长度)
含义:控制 TCP 监听队列的最大长度,避免连接溢出。
查看当前值:
sysctl net.core.somaxconn
临时调整:
sysctl -w net.core.somaxconn=65535
永久生效(写入 /etc/sysctl.conf
):
net.core.somaxconn = 65535
2. tcp_tw_reuse
(复用 TIME_WAIT 连接)
含义:允许复用 TIME_WAIT 状态的连接,减少端口耗尽。
配置:
net.ipv4.tcp_tw_reuse = 1
适用场景:高并发短连接(如 HTTP 短连接)。
3. tcp_fin_timeout
(FIN_WAIT 超时时间)
含义:控制连接关闭后等待 FIN 包的超时时间。
默认值:60s,可适当缩短(如 30s)。
配置:
net.ipv4.tcp_fin_timeout = 30
4. net.core.rmem_max/wmem_max
(TCP 缓冲区大小)
含义:调整 TCP 接收/发送缓冲区最大值,提升吞吐量。
配置:
net.core.rmem_max = 16777216 # 16MB
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
5. ulimit -n
(文件描述符限制)
含义:调整进程最大打开文件数(包括 TCP 连接)。
查看当前值:
ulimit -n
临时调整:
ulimit -n 65536
永久生效(写入 /etc/security/limits.conf
):
* soft nofile 65536
* hard nofile 65536
5.3 连接复用与网络优化
1. HTTP 连接池
作用:复用 HTTP 连接,减少握手开销。
实现方式:
- Java:
HttpClient
连接池; - Go:
http.Transport
连接池。
示例(Java HttpClient):
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.version(HttpClient.Version.HTTP_2)
.build();
2. DNS 预热
问题:DNS 解析延迟影响首次请求速度。
优化:
- 启动时预解析域名;
- 使用本地 DNS 缓存(如
dnsmasq
)。
示例:
InetAddress.getByName("api.example.com");
3. 跨 AZ/机房就近路由
策略:
- 使用智能 DNS(如阿里云 DNS、Route53);
- 服务网格(如 Istio)按地域路由;
- CDN 就近接入。
优势:减少网络延迟,提升用户体验。
5.4 小结
网关与网络/内核优化是高并发系统性能调优的基础环节,涵盖 Nginx 配置、内核参数调整、连接复用与网络路由优化。通过合理配置 keepalive
、worker_connections
、HTTP/2,调整内核参数(如 somaxconn
、tcp_tw_reuse
),以及使用连接池和就近路由,可以显著提升系统的网络吞吐能力与稳定性。
六、稳态与韧性(SLO/保护)
- SLO:面向 P99 延迟、错误预算驱动节流。
- 保护策略:限流→降级→熔断→隔离(舱壁/线程池);灰度/金丝雀发布,自动回滚;超时重试(幂等)。
- 读写分离的选择:写多强一致走主库;读多最终一致走从库/缓存。
接下来,我们详细拆解“稳态与韧性(SLO/保护)”部分的每一条策略,帮助你掌握高并发场景下系统稳定性保障的核心方法,包括服务等级目标(SLO)设计、保护策略实施以及读写分离的选择逻辑,确保系统在高压下仍能保持可靠运行。
6.1 SLO(服务等级目标)
1. 面向 P99 延迟
含义:以 99% 请求的延迟作为核心指标,避免仅关注平均值(P50)而忽略长尾问题。
示例:
- 定义 SLO:“99% 的订单查询请求延迟 ≤ 200ms”;
- 监控工具:Prometheus + Grafana(P99 延迟分位数)。
优化方向: - 优化慢 SQL、缓存穿透、热点 Key;
- 使用异步化(如 CompletableFuture)减少阻塞。
2. 错误预算驱动节流
含义:基于错误预算(Error Budget)控制变更节奏,避免频繁发布导致稳定性下降。
计算公式:
错误预算 = 100% - SLO(如 99.9% → 错误预算为 0.1%)
实践:
- 错误预算耗尽时,暂停发布并触发根因分析;
- 工具:SRE 平台(如 Google SRE Toolkit)。
6.2 保护策略
1. 限流 → 降级 → 熔断 → 隔离
限流(Rate Limiting)
作用:防止流量突增压垮系统。
策略:
- 令牌桶(Guava RateLimiter);
- 滑动窗口(Sentinel);
- 分布式限流(Redis + Lua)。
示例:
// Sentinel 限流规则
FlowRule rule = new FlowRule("orderService")
.setCount(1000) // 每秒 1000 次
.setGrade(RuleConstant.FLOW_GRADE_QPS);
FlowRuleManager.loadRules(Collections.singletonList(rule));
降级(Degradation)
作用:非核心功能故障时,牺牲部分体验保障核心流程。
策略:
- 读降级:缓存兜底(如默认商品推荐);
- 写降级:异步化(如订单日志延迟写入)。
示例:
@HystrixCommand(fallbackMethod = "getDefaultProduct")
public Product getProductDetail(Long id) {
return productService.getById(id);
}
熔断(Circuit Breaker)
作用:失败率达到阈值时,暂时停止调用,避免连锁故障。
策略:
- 熔断条件:10 秒内 50% 请求失败;
- 恢复策略:半开状态(允许少量试探请求)。
工具:Resilience4j、Hystrix。
示例:
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 50% 失败率触发熔断
.waitDurationInOpenState(Duration.ofSeconds(30)) // 熔断后等待 30s
.build();
隔离(舱壁/线程池)
作用:限制故障影响范围,防止资源耗尽。
策略:
- 线程池隔离(Hystrix);
- 信号量隔离(轻量级场景)。
示例:
// Hystrix 线程池隔离
@HystrixCommand(threadPoolKey = "orderPool", threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10"),
@HystrixProperty(name = "maxQueueSize", value = "20")
})
public void createOrder(Order order) { ... }
2. 灰度/金丝雀发布 + 自动回滚
灰度发布
流程:
- 全量流量切到旧版本;
- 逐步放量(1% → 10% → 50% → 100%);
- 监控错误率和延迟,异常时回滚。
工具:Istio、Nacos、Apollo。
金丝雀发布
特点:
- 基于用户特征(如 UserID 哈希)分流;
- 快速验证新版本稳定性。
示例:
# Nginx 按用户 ID 灰度
location /api {
if ($cookie_user_id ~ "^[0-9]{4}$") {
proxy_pass http://new-service;
}
proxy_pass http://old-service;
}
自动回滚
触发条件:
- 错误率超过阈值(如 5%);
- P99 延迟超过 SLO。
工具:Argo Rollouts、Spinnaker。
3. 超时重试(幂等)
策略:
- 设置合理超时(如 500ms);
- 重试次数限制(如 3 次);
- 幂等设计(如唯一订单号 + 状态机)。
示例:
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 100))
public void processOrder(String orderId) {
// 幂等检查
if (orderRepository.existsById(orderId)) {
return;
}
// 业务逻辑
}
6.3 读写分离的选择
1. 写多强一致走主库
场景:订单创建、支付回调等强一致性要求。
策略:
- 直接写主库,同步到从库;
- 使用分布式事务(如 Seata)保证一致性。
示例:
@Transactional
public void createOrder(Order order) {
masterRepository.save(order); // 强一致写主库
}
2. 读多最终一致走从库/缓存
场景:商品详情、用户信息等容忍短暂延迟。
策略:
- 读从库(异步同步);
- 缓存兜底(如 Redis + 过期时间)。
示例:
@Cacheable(value = "product", key = "#id")
public Product getProduct(Long id) {
return slaveRepository.findById(id).orElseGet(() -> masterRepository.findById(id));
}
6.4 小结
稳态与韧性设计是高并发系统的“安全网”,通过 SLO 驱动优化、限流→降级→熔断→隔离的保护策略,以及读写分离的合理选择,确保系统在流量洪峰、依赖故障、数据一致性挑战下仍能稳定运行。结合灰度发布、自动回滚和超时重试,可以进一步提升系统的容错能力和恢复速度。接下来,我们将进入“优化”的下一阶段:监控与可观测性,完善系统的全链路观测能力。
七、容量与验证(压测与容量模型)
- 容量模型:目标 RPS × 峰值系数 × 安全余量(≥30%);链路预算每跳耗时。
- 压测策略:流量回放/影子库;分阶段:单接口→关键链路→全链路;观察 P95/P99、CPU、GC、队列长度。
- 基线:每次优化后回归压测,留基线图;防“局部最优”。
接下来,我们详细拆解“容量与验证(压测与容量模型)”部分的每一条策略,帮助你掌握高并发场景下系统容量规划、压测实施与验证方法,确保系统在真实流量下仍能稳定运行,并具备可扩展的弹性能力。
7.1 容量模型
1. 目标 RPS × 峰值系数 × 安全余量(≥30%)
含义:通过数学模型预估系统所需容量,避免过载或资源浪费。
公式:
规划容量 = 目标 RPS × 峰值系数 × (1 + 安全余量)
- 目标 RPS:业务预期峰值(如 1万 QPS);
- 峰值系数:应对突发流量(如 1.5 倍);
- 安全余量:预留缓冲(≥30%)。
示例:
目标 RPS = 10,000
峰值系数 = 1.5
安全余量 = 30%
规划容量 = 10,000 × 1.5 × 1.3 = 19,500 RPS
2. 链路预算每跳耗时
含义:拆分全链路各环节耗时,识别瓶颈。
示例(电商下单链路):
环节 | 耗时(ms) | 占比 |
---|---|---|
网关 | 20 | 20% |
订单服务 | 50 | 50% |
支付服务 | 30 | 30% |
总计 | 100 | 100% |
优化方向:
- 优化高占比环节(如订单服务 SQL 慢查询);
- 并行化处理(如支付与库存扣减异步化)。
7.2 压测策略
1. 流量回放/影子库
流量回放
含义:录制生产流量,在测试环境回放,模拟真实场景。
工具:
- GoReplay(开源流量复制);
- JMeter + 录制插件。
示例:
goreplay --input-raw :80 --output-http http://test-service:8080
影子库
含义:压测流量写入独立数据库,避免污染生产数据。
实现:
- 分库分表路由(如 ShardingSphere);
- 环境标识(如请求头
X-Shadow: true
)。
示例:
if (request.getHeader("X-Shadow") != null) {
return shadowDataSource;
}
return masterDataSource;
2. 分阶段压测
阶段 1:单接口压测
目标:验证单个接口的性能极限。
工具:JMeter、wrk。
示例:
wrk -t12 -c400 -d30s http://api.example.com/order/create
阶段 2:关键链路压测
目标:测试核心业务流程(如下单、支付)。
策略:
- 模拟用户行为(如登录→加购→下单);
- 关联接口依赖(如 Redis、MySQL)。
阶段 3:全链路压测
目标:验证整体系统容量。
注意事项:
- 模拟网络延迟(如 ToC 200ms);
- 混合读写比例(如 70% 读 + 30% 写)。
3. 观察指标
核心指标
指标类型 | 具体指标 | 工具 |
---|---|---|
性能 | P95/P99 延迟、吞吐量 | Prometheus、Grafana |
资源 | CPU、内存、磁盘 I/O | Node Exporter |
中间件 | GC 频率、队列长度 | JMX、Arthas |
示例(Prometheus 查询):
# P99 延迟
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
# GC 频率
rate(jvm_gc_pause_seconds_count[5m])
7.3 基线与回归
1. 每次优化后回归压测
流程:
- 优化前记录基线(如 P99 延迟 100ms);
- 优化后重新压测,对比指标;
- 若性能下降,回滚优化。
示例:
# 优化前基线
wrk -t12 -c400 -d30s http://api.example.com/order/create > baseline.txt
# 优化后对比
wrk -t12 -c400 -d30s http://api.example.com/order/create > optimized.txt
diff baseline.txt optimized.txt
2. 留基线图
作用:可视化对比优化效果,避免“局部最优”。
工具:
- Grafana 仪表盘;
- JMeter 聚合报告。
示例:
优化前:P99=100ms, CPU=70%
优化后:P99=80ms, CPU=60% ✅
3. 防“局部最优”
问题:单环节优化可能导致整体性能下降(如缓存命中率提升但 GC 频繁)。
策略:
- 全链路视角分析;
- 长期监控(如 7 天稳定性观察)。
7.4 小结
容量与验证是高并发系统的“试金石”,通过科学的容量模型(RPS × 峰值系数 × 安全余量)、分阶段压测(单接口→关键链路→全链路)和严格的基线回归,确保系统在真实流量下仍能稳定运行。结合流量回放、影子库和核心指标监控(P99、CPU、GC),可以精准定位瓶颈并避免局部优化陷阱。接下来,我们将进入“优化”的下一阶段:监控与可观测性,完善系统的全链路观测与告警能力。
八、典型“提速 80%”清单(常中常赢)
- 打平热点:把读请求尽量打到本地/二级缓存;写扩散用 MQ 异步。
- 收敛强一致:仅把支付、库存等关键路径做强一致,其余最终一致。
- 压缩往返:合并小 IO、批量操作、长连接;把多 RPC并行化。
- 直击慢 SQL:TOP5 慢查询(80/20 法则)优先。
- 降 GC 压力:减少临时对象(DTO 映射、JSON 解析)、使用复用池。
接下来,我们详细拆解“典型‘提速 80%’清单(常中常赢)”部分的每一条策略,帮助你掌握高并发场景下最常见、最高效的优化手段,聚焦关键路径,用最小成本实现最大性能提升。
8.1 打平热点:读请求尽量打到本地/二级缓存,写扩散用 MQ 异步
1. 读请求尽量打到本地/二级缓存
目标:避免重复访问远程存储(如 Redis、DB),减少网络开销。
策略:
- 本地缓存:Caffeine、Guava Cache(适用于单机高频读);
- 二级缓存:本地缓存 + Redis(缓存穿透保护)。
示例:
// Caffeine 本地缓存
Cache<String, Product> localCache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
public Product getProduct(String id) {
return localCache.get(id, key -> redisTemplate.opsForValue().get(key));
}
适用场景:
- 商品详情、用户信息等读多写少数据;
- 热点 Key(如秒杀商品)。
2. 写扩散用 MQ 异步
目标:将写操作异步化,避免阻塞主流程。
策略:
- 关键路径同步写(如订单创建);
- 非关键路径异步写(如日志、通知)。
示例:
// 订单创建后异步发送 MQ
public void createOrder(Order order) {
orderRepository.save(order); // 同步写 DB
mqTemplate.send("order_topic", order); // 异步通知下游
}
适用场景:
- 订单状态变更、用户行为日志;
- 需要最终一致性的场景(如库存扣减)。
8.2 收敛强一致:仅把支付、库存等关键路径做强一致,其余最终一致
1. 关键路径做强一致
目标:核心业务(如支付、库存)必须保证数据实时一致。
策略:
- 分布式事务(Seata、TCC);
- 数据库事务 + 锁(如
SELECT FOR UPDATE
)。
示例:
@Transactional
public void deductStock(Long productId, int quantity) {
Product product = productRepository.findById(productId);
if (product.getStock() < quantity) {
throw new RuntimeException("库存不足");
}
product.setStock(product.getStock() - quantity);
productRepository.save(product);
}
2. 非关键路径最终一致
目标:降低非核心业务的耦合度和延迟。
策略:
- 异步补偿(如定时任务对账);
- 消息队列(如 Kafka 保证至少一次投递)。
示例:
// 用户积分更新异步化
public void updatePoints(Long userId, int points) {
mqTemplate.send("points_topic", new PointsEvent(userId, points));
}
适用场景:
- 用户积分、优惠券发放;
- 数据统计(如 PV/UV)。
8.3 压缩往返:合并小 IO、批量操作、长连接;把多 RPC 并行化
1. 合并小 IO 与批量操作
目标:减少网络请求次数,提升吞吐量。
策略:
- 批量查询(如
IN
语句替代循环查询); - 批量写入(如 Redis
mget
/mset
)。
示例:
// 批量查询商品
List<Product> products = productRepository.findAllByIds(Arrays.asList(1L, 2L, 3L));
// Redis 批量设置
Map<String, String> data = Map.of("key1", "value1", "key2", "value2");
redisTemplate.opsForValue().multiSet(data);
2. 长连接与多 RPC 并行化
目标:减少连接建立开销,缩短总耗时。
策略:
- HTTP Keep-Alive、gRPC 长连接;
- 并行调用(如 CompletableFuture)。
示例:
// 并行调用多个 RPC
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> userService.getById(userId));
CompletableFuture<Order> orderFuture = CompletableFuture.supplyAsync(() -> orderService.getById(orderId));
CompletableFuture.allOf(userFuture, orderFuture).join();
适用场景:
- 聚合服务(如订单详情页);
- 微服务间依赖调用。
8.4 直击慢 SQL:TOP5 慢查询(80/20 法则)优先
1. 定位慢查询
工具:
- MySQL 慢查询日志(
slow_query_log = ON
); - Prometheus + Grafana 监控 SQL 耗时。
示例:
-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 超过 1s 记录
2. 优化慢查询
策略:
- 添加索引(如联合索引);
- 避免
SELECT *
; - 分页优化(
WHERE id > ? LIMIT ?
替代OFFSET
)。
示例:
-- 优化前(全表扫描)
SELECT * FROM orders WHERE user_id = 100;
-- 优化后(索引覆盖)
CREATE INDEX idx_user_id ON orders(user_id);
SELECT id, amount FROM orders WHERE user_id = 100;
适用场景:
- 高频查询(如订单列表);
- 大表扫描(如日志表)。
8.5 降 GC 压力:减少临时对象(DTO 映射、JSON 解析)、使用复用池
1. 减少临时对象
目标:避免频繁创建对象导致 GC 频繁。
策略:
- 复用 DTO(如对象池);
- 优化 JSON 解析(如 Jackson
ObjectMapper
复用)。
示例:
// 复用 ObjectMapper(避免重复创建)
private static final ObjectMapper objectMapper = new ObjectMapper();
public String toJson(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
2. 使用复用池
目标:减少对象创建/销毁开销。
策略:
- 线程池(
ThreadPoolExecutor
); - 连接池(HikariCP、Redis 连接池)。
示例:
// HikariCP 连接池配置
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/db");
config.setMaximumPoolSize(20);
HikariDataSource dataSource = new HikariDataSource(config);
适用场景:
- 高频创建对象(如 HTTP 请求解析);
- 资源密集型操作(如数据库连接)。
8.6 小结
“提速 80%”清单聚焦高并发场景下的核心优化点:
- 打平热点:读缓存、写异步;
- 收敛强一致:关键路径强一致,其余最终一致;
- 压缩往返:批量操作、并行调用;
- 直击慢 SQL:优先优化 TOP5 慢查询;
- 降 GC 压力:减少临时对象、复用资源。
通过这些策略,可以快速定位性能瓶颈,用最小成本实现最大性能提升。接下来,我们将进入“优化”的下一阶段:监控与可观测性,完善系统的全链路观测与告警能力。
九、面试 30 秒回答模板(背诵版)
我先“量化”再“优化”。用 Prometheus/OTel 建立 RPS、P99、错误率、饱和度四象限看板,压测复现并用 JFR/async-profiler 和慢 SQL 日志定位热点。
应用侧按职责分池并限队列,引入异步+背压+熔断降级,G1 固定堆、降低对象分配和锁竞争;
数据侧通过覆盖索引、批量写、读写分离与分库分表,缓存用 Cache-Aside + 热点保护(布隆、逻辑过期、互斥重建)。
系统侧调优连接与内核参数,网关启用 HTTP/2 与 keepalive。
关键链路(如库存/支付)做强一致(Redis Lua 原子 + 最终异步落库),其他路径追求高可用 + 最终一致。
每次改动全链路压测对比基线,确保 P99 和错误率达标并留有容量余量。
下面我将“面试 30 秒回答模板”拆解为一页 A4 速记卡和模拟问答题库(附标准答案),方便你快速背诵和模拟面试演练。
📄 一页 A4 速记卡(速记版)
🎯 核心思路
“先量化,再优化”
建立四象限看板(RPS、P99、错误率、饱和度)→ 压测复现 → 定位热点(JFR/async-profiler + 慢 SQL)→ 分层优化 → 全链路压测对比基线。
📊 量化与监控
- 工具:Prometheus / OTel
- 指标:
- RPS(吞吐量)
- P99 延迟
- 错误率
- 饱和度(CPU/内存/队列)
⚙️ 应用侧优化
- 线程池:按职责分池 + 限队列
- 异步化:CompletableFuture / Reactor
- 保护机制:
- 背压(Backpressure)
- 熔断(Resilience4j)
- 降级(Hystrix)
- JVM 调优:
- G1 GC + 固定堆
- 减少对象分配
- 降低锁竞争
🗄️ 数据侧优化
- SQL:覆盖索引、批量写
- 架构:读写分离、分库分表
- 缓存:
- Cache-Aside 模式
- 热点保护:
- 布隆过滤器
- 逻辑过期
- 互斥重建
🌐 系统侧优化
- 网络:HTTP/2 + keepalive
- 内核参数:调优连接数、文件句柄
- 网关:启用长连接与压缩
🔄 一致性与可用性
- 强一致路径:库存/支付
- Redis Lua 原子操作
- 最终异步落库
- 其他路径:高可用 + 最终一致
✅ 验证与基线
- 全链路压测:对比基线
- 目标:
- P99 延迟达标
- 错误率可控
- 容量余量 ≥30%
📝 模拟问答题库(附标准答案)
Q1:如何系统性地优化一个高并发接口?
A:
我会先“量化”再“优化”。用 Prometheus/OTel 建立 RPS、P99、错误率、饱和度四象限看板,压测复现并用 JFR/async-profiler 和慢 SQL 日志定位热点。
应用侧按职责分池并限队列,引入异步+背压+熔断降级,G1 固定堆、降低对象分配和锁竞争;
数据侧通过覆盖索引、批量写、读写分离与分库分表,缓存用 Cache-Aside + 热点保护(布隆、逻辑过期、互斥重建)。
系统侧调优连接与内核参数,网关启用 HTTP/2 与 keepalive。
关键链路(如库存/支付)做强一致(Redis Lua 原子 + 最终异步落库),其他路径追求高可用 + 最终一致。每次改动全链路压测对比基线,确保 P99 和错误率达标并留有容量余量。
Q2:如何保证缓存与数据库的一致性?
A:
我会采用 Cache-Aside 模式:
- 读请求先查缓存,未命中则查 DB 并回写缓存;
- 写请求先更新 DB,再删除缓存(避免脏读)。
针对热点 Key,会加入 互斥重建(防止缓存击穿)和 逻辑过期(避免雪崩)。极端场景下用 布隆过滤器 防止缓存穿透。
Q3:如何优化慢 SQL?
A:
首先通过 慢查询日志 或 Prometheus 定位 TOP5 慢 SQL(80/20 法则)。
优化手段包括:
- 添加 覆盖索引(避免回表);
- 批量操作(减少 IO 次数);
- 分页优化(用
WHERE id > ?
替代OFFSET
);- 避免
SELECT *
,只查必要字段。
Q4:如何设计高可用的支付系统?
A:
支付系统需 强一致,我会:
- 用 Redis Lua 原子扣减库存;
- 异步落库(MQ 最终一致);
- 熔断降级非核心功能(如通知);
- 全链路压测确保 P99 ≤ 200ms,错误率 < 0.1%。
Q5:如何应对突发流量(如秒杀)?
A:
- 限流:Sentinel 按用户 ID 分桶;
- 缓存:本地缓存 + Redis 预热;
- 异步:MQ 削峰填谷;
- 降级:库存扣减后异步生成订单;
- 压测:提前模拟 10 倍流量验证容量。
💡 使用建议
- 速记卡:打印成 A4 纸,面试前快速浏览;
- 题库:模拟面试时自问自答,强化肌肉记忆;
- 扩展:结合实际项目经验补充案例(如“我在 XX 项目中用 Redis Lua 解决超卖问题”)。
📄 PDF 版速记卡(A4 单页)
你可以直接复制以下内容到 Word 或 Markdown 转 PDF 工具(如 Typora + Pandoc)生成打印版:
# 高并发优化速记卡
## 🎯 核心思路
**“先量化,再优化”**
1. 建立四象限看板:RPS、P99、错误率、饱和度
2. 压测复现 → 定位热点(JFR/async-profiler + 慢 SQL)
3. 分层优化 → 全链路压测对比基线
---
## 📊 量化与监控
- **工具**:Prometheus / OTel
- **指标**:
- RPS(吞吐量)
- P99 延迟
- 错误率
- 饱和度(CPU/内存/队列)
---
## ⚙️ 应用侧优化
- **线程池**:按职责分池 + 限队列
- **异步化**:CompletableFuture / Reactor
- **保护机制**:
- 背压(Backpressure)
- 熔断(Resilience4j)
- 降级(Hystrix)
- **JVM 调优**:
- G1 GC + 固定堆
- 减少对象分配
- 降低锁竞争
---
## 🗄️ 数据侧优化
- **SQL**:覆盖索引、批量写
- **架构**:读写分离、分库分表
- **缓存**:
- Cache-Aside 模式
- 热点保护:
- 布隆过滤器
- 逻辑过期
- 互斥重建
---
## 🌐 系统侧优化
- **网络**:HTTP/2 + keepalive
- **内核参数**:调优连接数、文件句柄
- **网关**:启用长连接与压缩
---
## 🔄 一致性与可用性
- **强一致路径**:库存/支付
- Redis Lua 原子操作
- 最终异步落库
- **其他路径**:高可用 + 最终一致
---
## ✅ 验证与基线
- **全链路压测**:对比基线
- **目标**:
- P99 延迟达标
- 错误率可控
- 容量余量 ≥30%
🃏 Anki 卡片(间隔重复记忆)
你可以将以下内容导入 Anki(支持 CSV 格式),便于每天复习:
导入格式(CSV)
Front,Back
如何系统性地优化高并发接口?,"先量化(四象限看板:RPS/P99/错误率/饱和度)→ 压测复现 → 定位热点(JFR/async-profiler+慢SQL)→ 分层优化(应用侧:分池+异步+熔断;数据侧:索引+缓存+分库;系统侧:HTTP/2+内核调优)→ 全链路压测对比基线。"
如何保证缓存一致性?,"Cache-Aside 模式:读先查缓存,未命中查DB并回写;写先更新DB再删缓存。热点用互斥重建+逻辑过期+布隆过滤器防穿透。"
如何优化慢 SQL?,"1. 慢日志定位TOP5;2. 加覆盖索引;3. 批量操作;4. 分页用WHERE替代OFFSET;5. 避免SELECT *。"
如何设计高可用支付系统?,"强一致:Redis Lua原子扣库存+MQ异步落库;高可用:熔断降级非核心功能;压测确保P99≤200ms,错误率<0.1%。"
如何应对秒杀流量?,"1. 限流(Sentinel分桶);2. 缓存预热;3. MQ削峰;4. 异步生成订单;5. 提前压测10倍流量。"
导入步骤
- 打开 Anki → 点击“导入文件” → 选择 CSV 文件;
- 字段映射:Front → “正面”,Back → “背面”;
- 选择卡片模板(建议用“基础”模板);
- 导入后即可每天复习。
💡 使用建议
- PDF 速记卡:打印出来贴在工位,面试前快速浏览;
- Anki 卡片:每天通勤/午休时刷 5-10 分钟,强化记忆;
- 扩展:结合项目经验在卡片背面添加案例(如“我在 XX 项目中用 Redis Lua 解决超卖”)。