跳到主要内容

性能调优综合方法论

问题

系统整体性能不达标,如何从 JVM、数据库、缓存、网络、代码多个维度系统性调优?

答案

调优原则

  1. 先度量后优化:没有数据就没有优化
  2. 优化瓶颈点:用 Amdahl 定律,优化占比最大的部分
  3. 空间换时间:缓存、预计算、冗余
  4. 避免过早优化:先保证正确性

调优全景图

JVM 调优

JVM 推荐配置(8C16G)
# 堆配置
-Xms8g -Xmx8g # 堆大小固定,避免动态扩缩
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m

# GC 选择
# JDK 11+: G1(默认)
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200 # 目标停顿 200ms
-XX:G1HeapRegionSize=8m
-XX:InitiatingHeapOccupancyPercent=45

# JDK 17+: ZGC(超低延迟)
-XX:+UseZGC
-XX:+ZGenerational # JDK 21 分代 ZGC

数据库调优

维度优化点
SQLEXPLAIN 分析、避免全表扫描、减少 JOIN
索引覆盖索引、联合索引最左前缀、避免索引失效
连接池HikariCP,10-20 连接
读写分离查询走从库
分库分表单表超 500 万考虑

详见 慢 SQL 排查数据库连接

缓存调优

多级缓存提升性能
// L1: 本地缓存(Caffeine,ms 级)
// L2: Redis 缓存(ms 级)
// L3: 数据库
public Object getData(String key) {
// L1
Object value = localCache.getIfPresent(key);
if (value != null) return value;

// L2
value = redisTemplate.opsForValue().get(key);
if (value != null) {
localCache.put(key, value);
return value;
}

// L3
value = db.query(key);
redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES);
localCache.put(key, value);
return value;
}

关注指标:

  • 缓存命中率 > 95%
  • Redis RT < 5ms

代码层调优

优化示例
批量操作批量 INSERT 代替循环单条 INSERT
异步化非核心逻辑用 MQ / @Async
并行化CompletableFuture 并行调用多个服务
减少序列化Protobuf / Kryo 代替 JSON
对象复用连接池、线程池、对象池
CompletableFuture 并行调用
// 串行:300ms + 200ms + 100ms = 600ms
// 并行:max(300, 200, 100) = 300ms
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> userService.getUser(id));
CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(() -> orderService.list(id));
CompletableFuture<Integer> pointFuture = CompletableFuture.supplyAsync(() -> pointService.getPoints(id));

CompletableFuture.allOf(userFuture, orderFuture, pointFuture).join();

UserProfileVO vo = new UserProfileVO();
vo.setUser(userFuture.get());
vo.setOrders(orderFuture.get());
vo.setPoints(pointFuture.get());

常见面试问题

Q1: 你做过哪些性能优化?

答案:(按场景回答)

用 STAR 法则:

  • S(场景):大促期间接口 P99 从 500ms 飙升到 3s
  • T(任务):优化到 P99 < 200ms
  • A(行动):链路追踪定位 → 慢 SQL 加索引 → 热点数据加缓存 → 非核心链路异步化
  • R(结果):P99 降到 100ms,QPS 提升 3 倍

Q2: 接口从 1s 优化到 100ms,思路是什么?

答案

  1. 链路追踪找慢点
  2. 数据库层:加索引、缓存热点查询
  3. 服务层:并行调用、异步化非核心逻辑
  4. 网络层:连接复用、减少序列化开销
  5. 代码层:批量操作、减少不必要的计算

Q3: GC 导致的延迟怎么优化?

答案

  • 升级 GC:CMS → G1 → ZGC
  • 调大堆减少 GC 频率
  • 减少对象分配(对象池复用)
  • 预热:启动后先跑一些请求让 JIT 编译

详见 频繁 Full GCJVM 调优

相关链接