1. 高并发JVM调优实战
1.1 内存参数优化
在高并发Java应用中,JVM内存配置是性能优化的第一道门槛。我经历过多次线上事故后发现,合理的堆内存设置能避免80%的GC相关问题。对于8核32G的典型生产环境,建议采用以下配置:
java复制-Xms24g -Xmx24g
-XX:NewRatio=2
-XX:SurvivorRatio=8
-XX:MetaspaceSize=512m
-XX:MaxMetaspaceSize=512m
关键经验:Metaspace务必设置固定大小。曾遇到动态扩容触发Full GC导致秒级停顿的案例,固定大小后GC时间从1.2s降至200ms以内。
1.2 G1GC实战参数
G1回收器在吞吐量和延迟之间取得了较好平衡,这是经过多个版本迭代验证的配置模板:
java复制-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
-XX:G1ReservePercent=15
-XX:ConcGCThreads=4
实测数据显示,相比默认参数,该配置在QPS 10万+的场景下将99%尾延迟从350ms降至150ms。注意ConcGCThreads应根据CPU核数调整,建议为总核数的1/4。
1.3 内存问题诊断三板斧
当出现内存异常时,我常用的诊断流程:
- 即时快照:
jmap -dump:live,format=b,file=heap.bin <pid> - 实时监控:
jstat -gcutil <pid> 1000 - 线程分析:
jstack <pid> > thread.txt
曾用这个流程定位过内存泄漏:发现Survivor区长期100%,最终查明是线程本地缓存未清理。
2. 线程池深度优化
2.1 参数黄金法则
线程池配置不是玄学,根据业务类型有明确公式:
- CPU密集型:
核心数 + 1 - IO密集型:
核心数 * (1 + 平均等待时间/平均计算时间)
电商订单服务的实测最佳配置:
java复制ThreadPoolExecutor(
16, // 16核服务器
32,
30L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5000),
new NamedThreadFactory("order-service"),
new CallerRunsPolicy()
)
2.2 队列选型对比
| 队列类型 | 特点 | 适用场景 |
|---|---|---|
| LinkedBlocking | 无界队列,易OOM | 已知流量峰值的场景 |
| ArrayBlocking | 有界队列,公平锁 | 严格限流的场景 |
| SynchronousQueue | 直接传递,无缓冲 | 高吞吐低延迟场景 |
| PriorityBlocking | 优先级队列 | 任务有优先级的场景 |
血泪教训:支付系统曾用无界队列,大促时积压50万任务导致OOM,改用ArrayBlockingQueue后稳定运行至今。
2.3 监控与动态调整
通过JMX实现线程池运行时调整:
java复制// 注册MBean
ManagementFactory.getPlatformMBeanServer().registerMBean(
new ThreadPoolAdmin(executor),
new ObjectName("com.app:type=ThreadPool,name=orderService")
);
// 动态修改核心线程数
executor.setCorePoolSize(newSize);
配套的监控指标应包括:
- 活跃线程数
- 队列积压量
- 拒绝任务数
- 平均执行耗时
3. Redis防护体系
3.1 缓存穿透解决方案
布隆过滤器实现方案对比:
| 方案 | 精度 | 内存消耗 | 性能 |
|---|---|---|---|
| Guava | 高 | 中 | 本地内存 |
| RedisBloom | 可调节 | 较高 | 网络IO |
| Redisson | 可调节 | 较高 | 网络IO |
生产环境推荐组合方案:
java复制// 本地缓存+Redis二级过滤
LoadingCache<String, Boolean> localCache = Caffeine.newBuilder()
.maximumSize(100_000)
.build(key -> redisBloomFilter.contains(key));
if (!localCache.get(key)) {
throw new InvalidRequestException();
}
3.2 热点Key发现与处理
通过监控发现热点Key的模式:
shell复制# Redis热点监控命令
redis-cli --hotkeys
redis-cli --bigkeys
处理策略对比:
- 本地缓存:适合读多写少,一致性要求不严格
- 分片存储:将热点分散到多个节点
- 限流降级:超过阈值返回默认值
3.3 分布式锁优化
Redisson多级锁实现方案:
java复制RLock lock = redisson.getLock("resource_lock");
try {
// 尝试获取锁,最多等待100秒,锁有效期30秒
if (lock.tryLock(100, 30, TimeUnit.SECONDS)) {
// 业务逻辑
}
} finally {
lock.unlock();
}
避坑指南:
- 必须设置锁超时时间
- 业务执行时间应远小于锁超时时间
- 使用线程ID作为锁标识,避免误删
4. 分库分表实战
4.1 ShardingSphere最佳实践
订单表分片配置模板:
yaml复制spring:
shardingsphere:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..3}.t_order_$->{0..7}
table-strategy:
inline:
sharding-column: order_id
algorithm-expression: t_order_$->{order_id % 8}
database-strategy:
inline:
sharding-column: user_id
algorithm-expression: ds$->{user_id % 4}
基因分片法示例:用户ID后2位作为分库基因,订单ID包含用户基因:
java复制// 生成带基因的订单ID
long userId = 123456;
int dbGene = userId % 100;
long orderId = (System.currentTimeMillis() << 16) | (dbGene << 8) | sequenceId;
4.2 分布式事务方案选型
| 方案 | 一致性 | 性能 | 复杂度 |
|---|---|---|---|
| XA | 强 | 差 | 高 |
| TCC | 最终 | 中 | 高 |
| SAGA | 最终 | 好 | 中 |
| 本地消息表 | 最终 | 好 | 低 |
支付系统采用TCC模式示例:
java复制@Transactional
public void makePayment() {
// Try阶段
accountService.freezeAmount();
inventoryService.lockStock();
// Confirm阶段
accountService.confirm();
inventoryService.confirm();
// 如失败进入Cancel阶段
}
5. 安全监控体系
5.1 OAuth2.0增强实践
JWT令牌增强方案:
java复制public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("tenant_id", getTenantId());
additionalInfo.put("login_ip", getClientIp());
((DefaultOAuth2AccessToken) accessToken)
.setAdditionalInformation(additionalInfo);
return accessToken;
}
}
安全防护措施:
- 使用HS512算法替代RS256
- 设置合理的过期时间(2-4小时)
- 实现令牌黑名单机制
5.2 SkyWalking深度监控
自定义追踪点最佳实践:
java复制@Trace(operationName = "Order/Create")
public Order createOrder() {
ActiveSpan.tag("order_type", "normal");
try {
// 业务逻辑
} catch (Exception e) {
ActiveSpan.error(e);
throw e;
}
}
线程池监控集成:
java复制Metrics.gauge("thread_pool.core_size",
() -> executor.getCorePoolSize());
Metrics.gauge("thread_pool.active_count",
() -> executor.getActiveCount());
5.3 熔断限流策略
Resilience4j组合策略:
java复制CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("orderService");
RateLimiter rateLimiter = RateLimiter.of(100, Duration.ofSeconds(1));
Supplier<Order> supplier = () -> orderService.create();
Supplier<Order> decorated = Decorators.ofSupplier(supplier)
.withCircuitBreaker(circuitBreaker)
.withRateLimiter(rateLimiter)
.decorate();
配置参考值:
- 熔断:失败率50%持续10秒触发
- 限流:每秒100请求
- 超时:2000毫秒
经过多个大促验证,这套配置能保证系统在流量激增300%时仍能提供降级服务。