共计 2093 个字符,预计需要花费 6 分钟才能阅读完成。
问题场景
在高并发业务场景中(如秒杀系统、实时交易平台),我们常遇到三类典型问题:

- 线程阻塞:当线程池配置不合理时,大量请求堆积导致线程饥饿。例如订单服务调用第三方支付接口,同步等待响应时线程无法释放。
- 锁竞争:热门商品库存扣减场景中,粗粒度锁(如方法级 synchronized)会造成线程串行执行,TPS 从 2000 骤降到 300。
- 缓存失效:缓存集中过期引发的雪崩效应,某电商大促期间因未设置缓存过期时间分散,导致 DB 瞬时 QPS 突破 5 万。
技术选型
线程控制方案对比
- 基础 ThreadPoolExecutor:
- 优点:支持核心 / 最大线程数、队列容量等精细调控
-
缺点:需手动处理任务拒绝策略(如记录日志或降级)
-
ForkJoinPool:
- 适用场景:CPU 密集型计算任务
- 局限性:任务拆分成本高,不适合 IO 密集型场景
锁实现选型
| 方案 | 适用场景 | 性能损耗(纳秒 / 次) |
|---|---|---|
| synchronized | 单机低竞争场景 | 15-20 |
| ReentrantLock | 需要尝试获取锁的场景 | 25-30 |
| Redis 分布式锁 | 跨 JVM 资源协调 | 5000+(网络开销) |
缓存策略对比
- 本地缓存(Caffeine):
- 命中率:98%(200W 商品数据)
-
耗时:50ns/ 次
-
Redis 集群:
- 命中率:95%
- 耗时:1.2ms/ 次(同机房)
核心实现
线程池优化配置
// 电商订单处理线程池
ThreadPoolExecutor orderExecutor = new ThreadPoolExecutor(
10, // 核心线程数 = CPU 核数 *2
50, // 最大线程数(根据压测结果调整)30, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000), // 根据内存设置合理队列大小
new NamedThreadFactory("order-process"),
// 自定义拒绝策略:降级为异步记录请求
(r, executor) -> log.warn("触发拒绝策略, 任务转入 MQ: {}", r)
);
细粒度锁实现
// 使用分段锁提升库存操作并发度
public class InventoryService {private final Striped<Lock> lockStriped = Striped.lock(16);
public boolean deductStock(Long itemId, int num) {Lock lock = lockStriped.get(itemId); // 按商品 ID 哈希取锁
try {if (lock.tryLock(100, TimeUnit.MILLISECONDS)) {
// 真实库存操作(略)return true;
}
} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();
}
return false;
}
}
多级缓存方案
// 结合 Caffeine 与 Redis
public class ProductCache {@Cacheable(value = "product", key = "#id")
public Product getProduct(Long id) {Product product = redisTemplate.opsForValue().get(buildKey(id));
if (product == null) {product = dbRepository.findById(id);
// 设置随机过期时间防雪崩
redisTemplate.opsForValue().set(buildKey(id),
product,
30 + ThreadLocalRandom.current().nextInt(30),
TimeUnit.MINUTES
);
}
return product;
}
}
性能验证
压测数据对比(4C8G 云服务器)
| 优化项 | 单机 QPS | 平均耗时 | GC 次数 /min |
|---|---|---|---|
| 初始方案 | 1,200 | 450ms | 15 |
| 线程池优化后 | 3,800 | 120ms | 8 |
| 加分段锁 | 8,500 | 65ms | 3 |
| 多级缓存 | 12,000 | 28ms | 1 |
JVM 监控关键指标
- Young GC 时间:从 80ms 降至 20ms
- 锁竞争比例:synchronized 的竞争率从 35% 降到 3%
- CPU 利用率:从 90% 波动趋于稳定的 75%
避坑指南
线程泄漏排查
- 使用
jstack导出线程栈 - 查找 WAITING 状态的线程
- 检查是否在等待不存在的 notify
# 示例诊断命令
jstack <pid> | grep -A 10 "WAITING"
死锁预防措施
- 锁获取超时:
tryLock(timeout, unit) - 按固定顺序获取多把锁
- 使用
jconsole死锁检测功能
缓存注意事项
- 大 Value 拆分:单 Value 不超过 10KB
- 热点 Key 探测:监控单个 Key 的 QPS 突增
- 缓存版本控制:采用
key_v2格式便于灰度
开放性问题
- 如何根据业务特征(读多写少 / 写多读少)选择缓存更新策略?
- 分布式场景下,RedLock 是否真的能完全避免锁失效问题?
- 当线程池队列积压时,应该扩容线程还是优化处理逻辑?
经过上述优化,我们的订单系统在双 11 大促期间稳定支撑了每秒 1.2 万笔交易。性能优化没有银弹,需要持续监控和迭代调整。
正文完
