你是否遇到过这些问题?
性能问题就像癌症,早发现早治疗;否则可能直接拖垮整个系统。
本文将从 代码、数据库、服务层、架构层 四个角度,全景式带你走进性能优化实战。
// ❌ 极低效,每次循环创建新对象
String result = "";
for (int i = 0; i < 1000; i++) {
result += i;
}
// ✅ 推荐方式:使用 StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
for (User user : userList) {
// ❌ 每次都查一次,数据库压力爆炸
UserDetail detail = userMapper.getDetailById(user.getId());
}
集合操作不当
ArrayList 查找慢时可以考虑 HashMap
遍历删除用 Iterator 而不是 forEach
年轻代频繁 Full GC?
推荐使用 G1 垃圾回收器,适合低延迟场景。
工具 | 用途 |
---|---|
JMH | 方法级性能基准测试 |
JVisualVM | JVM 监控与分析工具 |
YourKit | 商用强大 Java Profiler |
Arthas | 阿里开源,线上问题排查神器 |
EXPLAIN SELECT * FROM orders WHERE user_id = 12345;
索引优化:
使用覆盖索引、组合索引;
order by、like ‘%abc’ 不走索引需谨慎。
分页优化:避免深分页
-- ❌ 深分页
SELECT * FROM orders LIMIT 100000, 10;
-- ✅ 使用上次最大 ID 游标分页
SELECT * FROM orders WHERE id > #{lastId} LIMIT 10;
本地缓存(Caffeine):轻量级,延迟低;
分布式缓存(Redis):
缓存热点数据;
减轻数据库 QPS 压力。
Page<User> page = new Page<>(1, 10);
IPage<User> result = userMapper.selectPage(page, queryWrapper);
✅ 自动分页 SQL,避免写错 limit;
✅ 支持 count 优化(如 count(1) 替代 count(*))
使用链路追踪系统(如 Skywalking、Zipkin、Pinpoint)查看慢调用链:
Controller -> Service -> DB (2.3s) -> Redis (20ms) -> MQ (10ms)
找出瓶颈在哪儿,有的放矢。
// ❌ 阻塞接口
orderService.createOrder();
// ✅ 异步执行
CompletableFuture.runAsync(() -> orderService.createOrder(), executor);
自定义 ThreadPoolExecutor,合理设置核心线程数、队列容量,避免 OOM 或任务堆积。
限流: 防止被压垮,如使用 Sentinel 或 Guava RateLimiter;
熔断: 某服务超时,立即短路,如 Hystrix、Resilience4j;
@SentinelResource(value = "queryOrder", blockHandler = "fallback")
public Order queryOrder(String orderId) {
// 业务逻辑
}
图片、视频、静态文件走 CDN;
-单体服务臃肿 → 拆分为独立微服务;
-注意接口幂等性、事务一致性(可用 TCC、MQ事务消息)。
用户下单 → MQ → 异步落库
-使用 Kafka / RabbitMQ 缓冲突发请求;
-消费端可以设置限速、批量处理。
-主库写、从库读,提升并发读能力;
-根据业务字段(如 userId)进行分表。
实战案例:接口响应从 5 秒优化到 200ms
背景: 某活动页接口,首次访问耗时 5 秒,用户体验极差。
背景: 某活动页接口,首次访问耗时 5 秒,用户体验极差。
性能优化没有银弹,需要“码农级细心 + 架构师级视野”;
日常开发应具备性能意识,比如写 SQL 前先想索引,写接口前先考虑幂等与延迟;
建议定期压测、监控 QPS/RT、持续观察 GC 情况,预防系统崩溃于无声处。
《深入理解 Java 虚拟机》
《MySQL 实战45讲》
阿里《Java 开发手册》
阿里开源 Arthas 官网