Java大促案例

wen java案例 2

本文目录导读:

Java大促案例

  1. 大促系统核心业务场景
  2. 核心技术架构
  3. 核心代码实现
  4. 性能优化策略
  5. 监控与告警
  6. 高可用方案

我来为您设计一个Java大促(例如双11、618)的系统案例,包含核心业务场景、技术架构和代码示例。

大促系统核心业务场景

// 1. 秒杀系统
// 2. 优惠券系统
// 3. 订单系统
// 4. 库存系统
// 5. 支付系统
// 6. 消息推送系统

核心技术架构

// 技术栈
- Spring Cloud Alibaba (微服务)
- Redis (缓存/分布式锁)
- RabbitMQ/Kafka (消息队列)
- MySQL + MyBatis Plus
- Nginx + LVS (负载均衡)
- 分库分表 (ShardingSphere)
- 分布式事务 (Seata)

核心代码实现

秒杀系统实现

/**
 * 秒杀控制器
 */
@RestController
@RequestMapping("/seckill")
public class SeckillController {
    @Autowired
    private SeckillService seckillService;
    /**
     * 秒杀接口 - 使用令牌桶限流
     */
    @PostMapping("/doSeckill")
    @RateLimiter(limit = 100, timeout = 1000) // 自定义限流注解
    public Result doSeckill(@RequestParam("userId") Long userId,
                           @RequestParam("productId") Long productId) {
        try {
            // 1. 前置校验
            Result validateResult = seckillService.validateSeckill(userId, productId);
            if (!validateResult.isSuccess()) {
                return validateResult;
            }
            // 2. 执行秒杀
            SeckillResult result = seckillService.executeSeckill(userId, productId);
            // 3. 异步处理订单
            if (result.isSuccess()) {
                seckillService.asyncProcessOrder(result.getOrderId());
            }
            return Result.success(result);
        } catch (Exception e) {
            log.error("秒杀异常", e);
            return Result.error("秒杀失败");
        }
    }
}
/**
 * 秒杀服务实现
 */
@Service
public class SeckillServiceImpl implements SeckillService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private OrderMapper orderMapper;
    /**
     * 秒杀核心逻辑
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SeckillResult executeSeckill(Long userId, Long productId) {
        // 1. Redis预减库存
        Long stock = redisTemplate.opsForValue()
            .decrement("seckill_stock_" + productId);
        if (stock < 0) {
            // 库存不足,回补
            redisTemplate.opsForValue().increment("seckill_stock_" + productId);
            return SeckillResult.error("商品已售罄");
        }
        // 2. 防止用户重复秒杀
        Boolean ifAbsent = redisTemplate.opsForValue()
            .setIfAbsent("seckill_user_" + userId + "_" + productId, 
                        "1", 10, TimeUnit.MINUTES);
        if (Boolean.FALSE.equals(ifAbsent)) {
            return SeckillResult.error("请勿重复秒杀");
        }
        // 3. 发送消息到MQ异步创建订单
        SeckillMessage message = new SeckillMessage();
        message.setUserId(userId);
        message.setProductId(productId);
        rabbitTemplate.convertAndSend("seckill.exchange", 
                                    "seckill.order", message);
        return SeckillResult.success("秒杀成功");
    }
    /**
     * 预减库存 - 使用Lua脚本保证原子性
     */
    public boolean preReduceStock(Long productId, Integer quantity) {
        String script = "local stock = redis.call('get', KEYS[1]);" +
                       "if (stock - ARGV[1] >= 0) then" +
                       "    redis.call('decrby', KEYS[1], ARGV[1]);" +
                       "    return 1;" +
                       "end;" +
                       "return 0;";
        Long result = redisTemplate.execute(
            new DefaultRedisScript<>(script, Long.class),
            Arrays.asList("product_stock_" + productId),
            quantity.toString()
        );
        return result == 1;
    }
}

分布式锁实现

/**
 * 分布式锁工具类
 */
@Component
public class RedisLockUtil {
    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 基于Redis的分布式锁
     */
    public boolean tryLock(String lockKey, String requestId, 
                          long expireTime, TimeUnit timeUnit) {
        Boolean success = redisTemplate.opsForValue()
            .setIfAbsent(lockKey, requestId, expireTime, timeUnit);
        return Boolean.TRUE.equals(success);
    }
    /**
     * 释放锁 - Lua脚本保证原子性
     */
    public boolean releaseLock(String lockKey, String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                       "return redis.call('del', KEYS[1]) else return 0 end";
        Long result = redisTemplate.execute(
            new DefaultRedisScript<>(script, Long.class),
            Arrays.asList(lockKey),
            requestId
        );
        return result > 0;
    }
    /**
     * 使用示例
     */
    public void businessWithLock() {
        String lockKey = "business_lock";
        String requestId = UUID.randomUUID().toString();
        try {
            // 尝试获取锁,等待5秒
            boolean locked = tryLock(lockKey, requestId, 10, TimeUnit.SECONDS);
            if (!locked) {
                throw new RuntimeException("获取锁失败");
            }
            // 业务逻辑
            System.out.println("执行关键业务");
        } finally {
            // 释放锁
            releaseLock(lockKey, requestId);
        }
    }
}

优惠券系统

/**
 * 优惠券服务
 */
@Service
public class CouponService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private CouponMapper couponMapper;
    /**
     * 发放优惠券 - 异步批量发放
     */
    @Async("couponExecutor")
    public CompletableFuture<Void> batchIssueCoupons(List<Long> userIds, 
                                                     Long couponTemplateId) {
        // 使用Redis流水线批量处理
        redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
            for (Long userId : userIds) {
                String key = "user_coupon_" + userId;
                connection.rPush(key.getBytes(), 
                               couponTemplateId.toString().getBytes());
            }
            return null;
        });
        return CompletableFuture.completedFuture(null);
    }
    /**
     * 领取优惠券 - 防止超发
     */
    public Result claimCoupon(Long userId, Long couponId) {
        // 使用分布式锁防止超发
        String lockKey = "coupon_lock_" + couponId;
        String requestId = UUID.randomUUID().toString();
        if (!redisLockUtil.tryLock(lockKey, requestId, 5, TimeUnit.SECONDS)) {
            return Result.error("系统繁忙");
        }
        try {
            // 检查优惠券库存
            Long stock = redisTemplate.opsForValue()
                .decrement("coupon_stock_" + couponId);
            if (stock < 0) {
                return Result.error("优惠券已被抢完");
            }
            // 保存用户优惠券
            UserCoupon userCoupon = new UserCoupon();
            userCoupon.setUserId(userId);
            userCoupon.setCouponTemplateId(couponId);
            userCoupon.setStatus(1);
            userCoupon.setCreateTime(new Date());
            couponMapper.insert(userCoupon);
            return Result.success("领取成功");
        } finally {
            redisLockUtil.releaseLock(lockKey, requestId);
        }
    }
}

订单异步处理

/**
 * 订单消息消费者
 */
@Component
public class OrderMessageConsumer {
    @Autowired
    private OrderService orderService;
    @Autowired
    private StockService stockService;
    /**
     * 秒杀订单消息处理
     */
    @RabbitListener(queues = "seckill.order.queue")
    public void handleSeckillOrder(SeckillMessage message) {
        log.info("开始处理秒杀订单: {}", message);
        try {
            // 1. 创建订单
            Order order = new Order();
            order.setUserId(message.getUserId());
            order.setProductId(message.getProductId());
            order.setStatus(OrderStatus.CREATED);
            order.setCreateTime(new Date());
            orderService.createOrder(order);
            // 2. 扣减数据库库存(最终一致性)
            stockService.deductStock(message.getProductId(), 1);
            // 3. 发送创建成功消息
            rabbitTemplate.convertAndSend("order.exchange", 
                                        "order.created", order);
        } catch (Exception e) {
            log.error("处理秒杀订单失败", e);
            // 重新入队或标记为失败
            message.setRetryCount(message.getRetryCount() + 1);
            if (message.getRetryCount() < 3) {
                rabbitTemplate.convertAndSend("seckill.exchange", 
                                            "seckill.delay.order", message);
            }
        }
    }
    /**
     * 订单超时取消
     */
    @RabbitListener(queues = "order.delay.queue")
    public void handleOrderTimeout(Long orderId) {
        Order order = orderService.getById(orderId);
        if (order != null && order.getStatus() == OrderStatus.CREATED) {
            // 取消订单
            orderService.cancelOrder(orderId);
            // 恢复库存
            stockService.restoreStock(order.getProductId(), 1);
        }
    }
}

热点数据缓存

/**
 * 商品缓存服务
 */
@Service
public class ProductCacheService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ProductMapper productMapper;
    private static final String PRODUCT_CACHE_KEY = "product:detail:";
    /**
     * 商品详情缓存 - 使用Caffeine本地缓存 + Redis
     */
    @Cacheable(value = "productDetail", key = "#productId")
    public ProductDetail getProductDetail(Long productId) {
        // 1. 先从本地缓存获取
        ProductDetail localCache = getFromLocalCache(productId);
        if (localCache != null) {
            return localCache;
        }
        // 2. 从Redis缓存获取
        String redisKey = PRODUCT_CACHE_KEY + productId;
        ProductDetail redisCache = getFromRedis(redisKey);
        if (redisCache != null) {
            // 异步更新本地缓存
            updateLocalCache(productId, redisCache);
            return redisCache;
        }
        // 3. 从数据库查询(使用分布式锁防止缓存击穿)
        String lockKey = "product_lock_" + productId;
        String requestId = UUID.randomUUID().toString();
        if (redisLockUtil.tryLock(lockKey, requestId, 5, TimeUnit.SECONDS)) {
            try {
                // 双重检查
                ProductDetail dbCache = getFromRedis(redisKey);
                if (dbCache != null) {
                    return dbCache;
                }
                // 查询数据库
                ProductDetail detail = productMapper.getDetail(productId);
                // 空值缓存(防止缓存穿透)
                if (detail == null) {
                    redisTemplate.opsForValue()
                        .set(redisKey, "", 60, TimeUnit.SECONDS);
                    return null;
                }
                // 缓存到Redis(设置随机过期时间防止雪崩)
                int expireTime = 300 + new Random().nextInt(300);
                redisTemplate.opsForValue()
                    .set(redisKey, JSON.toJSONString(detail), 
                         expireTime, TimeUnit.SECONDS);
                return detail;
            } finally {
                redisLockUtil.releaseLock(lockKey, requestId);
            }
        }
        // 获取锁失败,返回默认值
        return getDefaultProductDetail(productId);
    }
}

流量控制与降级

/**
 * 熔断降级配置
 */
@Configuration
public class ResilienceConfig {
    /**
     * 熔断器配置
     */
    @Bean
    public Customizer<Resilience4JCircuitBreakerFactory> circuitBreakerConfig() {
        return factory -> factory.configureDefault(
            id -> new Resilience4JConfigBuilder(id)
                .circuitBreakerConfig(
                    io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.custom()
                        .failureRateThreshold(50)  // 失败率阈值
                        .waitDurationInOpenState(Duration.ofMillis(10000)) // 熔断时间
                        .slidingWindowSize(100)     // 滑动窗口大小
                        .build()
                )
                .timeLimiterConfig(
                    TimeLimiterConfig.custom()
                        .timeoutDuration(Duration.ofSeconds(3))
                        .build()
                )
                .build()
        );
    }
    /**
     * 使用示例
     */
    @CircuitBreaker(name = "productService", fallbackMethod = "fallback")
    public Product getProduct(Long productId) {
        // 调用微服务
        return restTemplate.getForObject(
            "http://product-service/product/" + productId, 
            Product.class
        );
    }
    /**
     * 降级方法
     */
    public Product fallback(Long productId, Throwable t) {
        log.error("获取商品信息失败,使用降级数据: {}", productId, t);
        Product fallbackProduct = new Product();
        fallbackProduct.setId(productId);
        fallbackProduct.setName("热门商品");
        fallbackProduct.setPrice(new BigDecimal("0.01"));
        return fallbackProduct;
    }
}

数据库分库分表

/**
 * 分片策略配置
 */
@Configuration
public class ShardingConfig {
    /**
     * 订单表分片策略(按用户ID)
     */
    @Bean
    public ShardingRuleConfiguration orderShardingRule() {
        ShardingRuleConfiguration config = new ShardingRuleConfiguration();
        // 订单表配置
        TableRuleConfiguration orderTableRule = new TableRuleConfiguration(
            "t_order", "ds0.t_order_$->{0..4}");
        // 分片算法:按用户ID取模
        orderTableRule.setTableShardingStrategyConfig(
            new InlineShardingStrategyConfiguration("user_id", "t_order_user_id_$->{user_id % 5}"));
        config.getTableRuleConfigs().add(orderTableRule);
        return config;
    }
    /**
     * 订单查询优化 - 使用用户ID路由
     */
    @Service
    public class OrderQueryService {
        @Autowired
        private OrderMapper orderMapper;
        public List<Order> getOrdersByUserId(Long userId) {
            // 直接按用户ID查询(会路由到正确的分片)
            return orderMapper.selectByUserId(userId);
        }
        public Order getOrderById(Long orderId) {
            // 如果是按订单号查询,需要同时提供用户ID
            // 或在订单号中嵌入分片信息
            return orderMapper.selectByOrderId(orderId);
        }
    }
}

性能优化策略

@Component
public class PerformanceOptimizer {
    /**
     * 1. 多级缓存策略
     */
    public void cacheStrategy() {
        // 本地缓存(Caffeine)- 1分钟
        Cache<String, Object> localCache = Caffeine.newBuilder()
            .maximumSize(10_000)
            .expireAfterWrite(1, TimeUnit.MINUTES)
            .build();
        // Redis缓存 - 5分钟
        // 数据库 - 永久
    }
    /**
     * 2. 批量处理优化
     */
    public void batchOptimize() {
        // 批量插入
        List<Order> orders = new ArrayList<>();
        sqlSessionTemplate.insert("batchInsertOrders", orders);
        // 批量查询
        List<Long> userIds = Arrays.asList(1L, 2L, 3L);
        List<User> users = userMapper.selectBatchIds(userIds);
    }
    /**
     * 3. 动态配置调整
     */
    @Autowired
    private NacosConfigService configService;
    public void dynamicConfig() {
        // 动态调整限流阈值
        String rateLimit = configService.getConfig("seckill.rate.limit", 
                                                 "DEFAULT_GROUP", 5000);
        // 动态调整线程池大小
        String threadPoolSize = configService.getConfig("seckill.thread.pool",
                                                      "DEFAULT_GROUP", 200);
    }
}

监控与告警

/**
 * 大促监控指标
 */
@Component
public class PrometheusMetrics {
    private final Counter seckillRequests;
    private final Counter seckillSuccess;
    private final Counter seckillFail;
    private final Gauge systemQPS;
    public PrometheusMetrics() {
        // 秒杀请求数
        seckillRequests = Counter.build()
            .name("seckill_requests_total")
            .help("Total seckill requests")
            .register();
        // 秒杀成功数
        seckillSuccess = Counter.build()
            .name("seckill_success_total")
            .help("Total success seckill")
            .register();
        // 秒杀失败数
        seckillFail = Counter.build()
            .name("seckill_fail_total")
            .help("Total fail seckill")
            .register();
        // QPS监控
        systemQPS = Gauge.build()
            .name("system_qps")
            .help("Current QPS")
            .register();
    }
}

高可用方案

/**
 * 大促保障策略
 */
@Configuration
public class HighAvailabilityConfig {
    /**
     * 1. 多地域部署
     * 2. 多活架构
     * 3. 弹性伸缩
     * 4. 链路追踪
     */
    /**
     * 全链路压测
     */
    @Test
    public void performanceTest() {
        // 使用JMeter或阿里云PTS进行压测
        // 每秒并发请求数
        int concurrency = 10000;
        // 模拟用户行为
        // 1. 浏览商品
        // 2. 加入购物车
        // 3. 下单
        // 4. 支付
    }
    /**
     * 容灾演练
     */
    public void disasterRecovery() {
        // 1. 模拟Redis宕机
        // 2. 模拟MySQL宕机
        // 3. 模拟MQ宕机
        // 4. 验证降级方案
    }
}

这个Java大促案例涵盖了:

  1. 秒杀系统:Redis预减库存 + MQ异步处理
  2. 分布式锁:防止超卖和重复操作
  3. 优惠券系统:异步批量发放
  4. 订单处理:消息队列异步解耦
  5. 缓存优化:多级缓存防击穿
  6. 熔断降级:保障系统稳定
  7. 分库分表:处理大数据量
  8. 监控告警:实时掌握系统状态

您可以根据实际业务需求,选择合适的模块进行实现和优化。

抱歉,评论功能暂时关闭!