java性能优化

1.缓存架构优化

// 多级缓存实现
@Service
public class MultiLevelCacheService {
    @Autowired
    private CaffeineCacheManager localCache;  // 本地缓存
    @Autowired 
    private RedisTemplate redisTemplate;      // 分布式缓存
    
    public Object get(String key) {
        // 1. 查本地缓存
        Object value = localCache.get(key);
        if(value != null) {
            return value;
        }
        
        // 2. 查分布式缓存
        value = redisTemplate.opsForValue().get(key);
        if(value != null) {
            // 回填本地缓存
            localCache.put(key, value);
            return value;
        }
        
        // 3. 查数据库
        value = getFromDB(key);
        if(value != null) {
            // 更新缓存
            redisTemplate.opsForValue().set(key, value);
            localCache.put(key, value); 
        }
        return value;
    }
    
    // 缓存预热
    @PostConstruct
    public void warmUp() {
        // 加载热点数据到Redis
        List<HotKey> hotKeys = getHotKeys();
        for(HotKey key : hotKeys) {
            String value = getFromDB(key);
            redisTemplate.opsForValue().set(key, value);
        }
    }
}

2. 数据库优化

-- 索引优化
ALTER TABLE red_packet ADD INDEX idx_user_id(user_id);
ALTER TABLE red_packet ADD INDEX idx_status_created(status, created_time);

-- SQL改写示例
-- 优化前
SELECT * FROM red_packet WHERE user_id = 1 ORDER BY created_time DESC;

-- 优化后
SELECT id,amount,status 
FROM red_packet FORCE INDEX(idx_user_id)
WHERE user_id = 1 
ORDER BY created_time DESC 
LIMIT 10;

-- 分库分表
-- 按用户ID分库
database_${user_id % 4}

-- 按时间分表
red_packet_${yyyyMM}

3.JVM调优

# JVM参数优化
-Xms4g -Xmx4g # 堆内存初始和最大值设置一致,避免扩容
-XX:+UseG1GC  # 使用G1垃圾收集器
-XX:MaxGCPauseMillis=200 # GC停顿时间目标
-XX:+HeapDumpOnOutOfMemoryError # OOM时dump堆
-XX:+PrintGCDetails # 打印GC详细日志
-XX:+PrintGCDateStamps

4.线程池优化

@Configuration
public class ThreadPoolConfig {
    
    @Bean
    public ThreadPoolExecutor businessThreadPool() {
        return new ThreadPoolExecutor(
            20,                       // 核心线程数
            50,                      // 最大线程数 
            60L,                     // 空闲线程存活时间
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(500),  // 工作队列
            new ThreadFactoryBuilder()
                .setNameFormat("business-thread-%d")
                .build(),
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );
    }
    
    // 线程池监控
    @Scheduled(fixedRate = 5000)
    public void monitorThreadPool() {
        ThreadPoolExecutor executor = businessThreadPool();
        log.info("线程池状态: " +
                "活跃线程数:{}, " +
                "完成任务数:{}, " +
                "队列任务数:{}", 
                executor.getActiveCount(),
                executor.getCompletedTaskCount(),
                executor.getQueue().size());
    }
}

 5.网络传输优化

// 1. 使用protobuf压缩传输数据
@Data
@Message
public class RedPacketProto {
    @Tag(1)
    private Long id;
    @Tag(2) 
    private BigDecimal amount;
    @Tag(3)
    private Integer status;
}

// 2. HTTP响应GZIP压缩
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public GZipFilter gzipFilter() {
        return new GZipFilter();
    }
}

// 3. 长连接复用
@Bean
public RestTemplate restTemplate() {
    HttpComponentsClientHttpRequestFactory factory = 
        new HttpComponentsClientHttpRequestFactory();
    factory.setConnectionRequestTimeout(1000);
    factory.setConnectTimeout(1000);
    factory.setReadTimeout(3000);
    // 开启连接池
    PoolingHttpClientConnectionManager cm = 
        new PoolingHttpClientConnectionManager();
    cm.setMaxTotal(200);
    cm.setDefaultMaxPerRoute(20);
    factory.setHttpClient(
        HttpClients.custom().setConnectionManager(cm).build()
    );
    return new RestTemplate(factory);
}

6.接口优化

@RestController
@RequestMapping("/api/red-packet")
public class RedPacketController {
    
    // 1. 接口合并
    @GetMapping("/detail")
    public Result getDetail(Long packetId) {
        // 并行调用多个接口
        CompletableFuture<RedPacketInfo> packetFuture = 
            CompletableFuture.supplyAsync(() -> 
                getRedPacketInfo(packetId)
            );
            
        CompletableFuture<List<GrabRecord>> recordsFuture = 
            CompletableFuture.supplyAsync(() -> 
                getGrabRecords(packetId)
            );
            
        CompletableFuture<UserInfo> userFuture = 
            CompletableFuture.supplyAsync(() -> 
                getUserInfo(packetId)
            );
        
        // 等待所有结果返回    
        CompletableFuture.allOf(
            packetFuture, 
            recordsFuture,
            userFuture
        ).join();
        
        return Result.success(new DetailVO(
            packetFuture.get(),
            recordsFuture.get(),
            userFuture.get()
        ));
    }
    
    // 2. 返回结果优化
    @GetMapping("/list")
    public Result getList(RedPacketQuery query) {
        // 只返回必要字段
        return redPacketService.getList(query)
            .stream()
            .map(packet -> {
                RedPacketVO vo = new RedPacketVO();
                vo.setId(packet.getId());
                vo.setAmount(packet.getAmount());
                vo.setStatus(packet.getStatus());
                return vo;
            })
            .collect(Collectors.toList());
    }
}

7.系统监控

@Aspect
@Component
public class PerformanceMonitor {
    
    @Around("execution(* com.xx.controller.*.*(..))")
    public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        String methodName = pjp.getSignature().getName();
        
        try {
            return pjp.proceed();
        } finally {
            long end = System.currentTimeMillis();
            // 记录方法执行时间
            Metrics.timer("method.latency")
                .tag("method", methodName)
                .record(end - start, TimeUnit.MILLISECONDS);
                
            // 记录QPS
            Metrics.counter("method.qps")
                .tag("method", methodName)
                .increment();
        }
    }
}

8.预防措施

@Configuration
public class RedisConfig {
    
    // 1. 布隆过滤器防缓存穿透
    @Bean
    public BloomFilter<String> bloomFilter() {
        return BloomFilter.create(
            Funnels.stringFunnel(Charset.defaultCharset()),
            1000000,  // 预计元素数量
            0.01      // 误判率
        );
    }
    
    // 2. 缓存雪崩解决
    @Bean 
    public RedisCacheConfiguration redisCacheConfiguration() {
        return RedisCacheConfiguration
            .defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(30))  // 统一过期时间
            .serializeValuesWith(
                RedisSerializationContext
                    .SerializationPair
                    .fromSerializer(new GenericJackson2JsonRedisSerializer())
            );
    }
    
    // 3. 热点缓存永不过期
    @PostConstruct
    public void initHotCache() {
        String key = "hot_red_packet";
        redisTemplate.opsForValue().set(key, value, -1); // 永不过期
    }
}

9.自适应限流

// 基于滑动时间窗口的自适应限流
public class AdaptiveRateLimiter {
    // 时间窗口(毫秒)
    private long windowTime = 1000;
    // 窗口内最大请求数
    private long maxRequests = 1000;
    // 每个窗口的计数器
    private Map<Long, AtomicLong> counters = new ConcurrentHashMap<>();
    
    public boolean tryAcquire() {
        long now = System.currentTimeMillis();
        long windowStart = now - windowTime;
        
        // 清理过期窗口
        counters.entrySet().removeIf(
            entry -> entry.getKey() < windowStart
        );
        
        // 当前窗口计数器
        AtomicLong counter = counters.computeIfAbsent(
            now, k -> new AtomicLong()
        );
        
        // 获取当前窗口内的请求总数
        long totalRequests = counters.values().stream()
            .mapToLong(AtomicLong::get)
            .sum();
            
        // 根据系统负载动态调整限流阈值
        double cpuLoad = getSystemCpuLoad();
        long adjustedLimit = (long)(maxRequests * (1 - cpuLoad));
        
        return totalRequests < adjustedLimit && 
            counter.incrementAndGet() <= adjustedLimit;
    }
}

10.热点数据实时统计 

// 使用RingBuffer实现滑动窗口热点统计
public class HotKeyDetector {
    // 环形缓冲区
    private RingBuffer<HotKeyCounter> ringBuffer;
    
    // 初始化RingBuffer
    public HotKeyDetector(int bufferSize) {
        this.ringBuffer = RingBuffer.createSingleProducer(
            HotKeyCounter::new,
            bufferSize,
            new YieldingWaitStrategy()
        );
        
        // 启动消费者线程
        DisruptorConsumer consumer = new DisruptorConsumer();
        ringBuffer.addGatingSequences(consumer.getSequence());
        EXECUTOR.submit(consumer);
    }
    
    // 记录热点key访问
    public void record(String key) {
        long sequence = ringBuffer.next();
        try {
            HotKeyCounter counter = ringBuffer.get(sequence);
            counter.setKey(key);
            counter.incrementCount();
        } finally {
            ringBuffer.publish(sequence);
        }
    }
    
    // 消费者处理逻辑
    private class DisruptorConsumer implements Runnable {
        private Sequence sequence = new Sequence();
        
        @Override
        public void run() {
            while (true) {
                try {
                    long available = ringBuffer.getCursor();
                    long current = sequence.get();
                    
                    for (long i = current + 1; i <= available; i++) {
                        HotKeyCounter counter = ringBuffer.get(i);
                        // 更新热点统计
                        updateHotKey(counter);
                        sequence.set(i);
                    }
                } catch (Exception e) {
                    log.error("处理热点统计异常", e);
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王爱编程啊

请多多鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值