怎么对高并发场景下做系统性能调优?

内容纲要

高并发性能调优是一项系统化工程,需要从“度量 → 定位 → 优化 → 验证”四个关键环节入手,形成闭环管理。

本文整理了一份实战导向的“高并发性能调优作战清单 + 面试速答模版”,不仅覆盖全流程技术要点,还提供可直接复述的表达框架,帮助你在实际工作中从容应对性能瓶颈,也能在面试现场条理清晰地展现专业能力。

无论是排查线上问题还是准备技术面试,这份清单都能成为你的高效工具。接下来,我们将逐一拆解每个环节的核心策略与操作要点,助你快速掌握高并发调优的完整打法。

一、度量与定位(先量化,再下手)

  • 核心指标(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:慢查询或带宽瓶颈。

应用场景

  • 判断是否需要扩容;
  • 定位资源瓶颈。

工具topvmstatiostatnmon、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)过高。

排查方法pingtraceroutemtr


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。
频繁装箱:如 intInteger 转换,增加 GC 压力。
建议

  • 使用基本类型;
  • 拆分大对象;
  • 复用对象(如对象池)。

4. 复用编解码缓冲

场景:网络通信、序列化/反序列化频繁分配缓冲区。
优化:使用 ByteBuffer 池或 NettyByteBuf 池,减少 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());
}

优化:使用 INJOIN 一次性查询。


避免 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(旁路缓存)

流程

  1. 先查缓存;
  2. 缓存未命中,查数据库;
  3. 写入缓存。

注意:更新时先更新数据库,再删除缓存。


避免大 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_connectionsserver_tokens off;HTTP/2;合并小响应。
  • 内核参数somaxconntcp_tw_reusetcp_fin_timeoutnet.core.rmem_max/wmem_maxulimit -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 配置、内核参数调整、连接复用与网络路由优化。通过合理配置 keepaliveworker_connections、HTTP/2,调整内核参数(如 somaxconntcp_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. 全量流量切到旧版本;
  2. 逐步放量(1% → 10% → 50% → 100%);
  3. 监控错误率和延迟,异常时回滚。
    工具: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. 每次优化后回归压测

流程

  1. 优化前记录基线(如 P99 延迟 100ms);
  2. 优化后重新压测,对比指标;
  3. 若性能下降,回滚优化。

示例

# 优化前基线
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%”清单聚焦高并发场景下的核心优化点:

  1. 打平热点:读缓存、写异步;
  2. 收敛强一致:关键路径强一致,其余最终一致;
  3. 压缩往返:批量操作、并行调用;
  4. 直击慢 SQL:优先优化 TOP5 慢查询;
  5. 降 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 模式

  1. 读请求先查缓存,未命中则查 DB 并回写缓存;
  2. 写请求先更新 DB,再删除缓存(避免脏读)。
    针对热点 Key,会加入 互斥重建(防止缓存击穿)和 逻辑过期(避免雪崩)。极端场景下用 布隆过滤器 防止缓存穿透。

Q3:如何优化慢 SQL?

A

首先通过 慢查询日志 或 Prometheus 定位 TOP5 慢 SQL(80/20 法则)。
优化手段包括:

  1. 添加 覆盖索引(避免回表);
  2. 批量操作(减少 IO 次数);
  3. 分页优化(用 WHERE id > ? 替代 OFFSET);
  4. 避免 SELECT *,只查必要字段。

Q4:如何设计高可用的支付系统?

A

支付系统需 强一致,我会:

  1. Redis Lua 原子扣减库存;
  2. 异步落库(MQ 最终一致);
  3. 熔断降级非核心功能(如通知);
  4. 全链路压测确保 P99 ≤ 200ms,错误率 < 0.1%。

Q5:如何应对突发流量(如秒杀)?

A

  1. 限流:Sentinel 按用户 ID 分桶;
  2. 缓存:本地缓存 + Redis 预热;
  3. 异步:MQ 削峰填谷;
  4. 降级:库存扣减后异步生成订单;
  5. 压测:提前模拟 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倍流量。"

导入步骤

  1. 打开 Anki → 点击“导入文件” → 选择 CSV 文件;
  2. 字段映射:Front → “正面”,Back → “背面”;
  3. 选择卡片模板(建议用“基础”模板);
  4. 导入后即可每天复习。

💡 使用建议

  • PDF 速记卡:打印出来贴在工位,面试前快速浏览;
  • Anki 卡片:每天通勤/午休时刷 5-10 分钟,强化记忆;
  • 扩展:结合项目经验在卡片背面添加案例(如“我在 XX 项目中用 Redis Lua 解决超卖”)。

高级软件工程师、高级大数据分析师、人工智能专家

Leave a Comment

您的电子邮箱地址不会被公开。 必填项已用*标注

close
arrow_upward