基于 Redis 的幂等性设计:SpringBoot @Async 在高并发 MySQL 日志存储中的应用

发布于:2025-06-19 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、问题描述

在高并发场景下,大量设备实时上报状态数据,需要异步保存到MySQL,同时需要解决幂等性校验和线程池耗尽问题。

二、解决方案

1. 幂等性控制

作用:确保同一请求无论执行多少次,结果都一致,避免重复处理。

实现方式

  • 唯一标识:设备ID + 时间戳组合
  • Redis原子操作:SET NX EX实现原子校验
  • 多级保障:Redis快速判断 + 数据库唯一索引 + 业务层查询确认
  • 超时机制:设置合理过期时间,避免永久占用资源

2. 防止线程池耗尽

策略

  • 合理配置线程池
    • 核心线程数:CPU核心数×2
    • 最大线程数:100
    • 队列容量:500
    • 拒绝策略:CallerRunsPolicy(压力返回调用方)
  • 快速失败:幂等校验快速过滤重复请求
  • 监控告警:建议添加线程池监控指标

3. 异步处理模式

CompletableFuture等待结果模式

  • 控制器等待异步操作完成后返回结果
  • 设置超时时间(5秒)避免无限等待
  • 超时返回HTTP 202状态码,提供状态查询接口

三、示例

1.Controller

@PostMapping("/{deviceId}/status")
public ResponseEntity<?> reportStatus(
        @PathVariable String deviceId,
        @RequestParam("timestamp") long timestamp,
        @RequestBody DeviceStatus status) {
   
    
    String requestId = "device:" + deviceId + ":status:" + timestamp;
    
    try {
   
        // 等待异步操作完成(最多5秒)
        deviceStatusService.processDeviceStatus(requestId, deviceId, timestamp, status)
                .get(5, TimeUnit.SECONDS);
        
        return ResponseEntity.ok().build();
    } catch (TimeoutException e) {
   
        return ResponseEntity.accepted()
                .header("X-Request-ID", requestId)
                .build();
    } catch (Exception e) {
   
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }
}

2.Service

@Async("deviceStatusExecutor")
public CompletableFuture<Void> processDeviceStatus(
        

网站公告

今日签到

点亮在社区的每一天
去签到