1. 需求分析
-
高并发:大量用户同时抢购,系统需要支持高并发请求。
-
库存一致性:避免超卖(库存减为负数)或数据不一致。
-
高性能:响应时间要短,用户体验要好。
-
公平性:先到先得,避免作弊。
2. 技术选型
-
缓存:使用 Redis 缓存商品库存和秒杀结果,减少数据库压力。
-
消息队列:使用 RabbitMQ 或 Kafka 异步处理订单,削峰填谷。
-
数据库:MySQL 存储订单和商品信息,使用事务保证数据一致性。
-
分布式锁:使用 Redis 或 Zookeeper 实现分布式锁,避免超卖。
3. 系统架构设计
-
前端:
-
静态页面缓存,减少服务器压力。
-
倒计时结束后,按钮可点击,用户提交秒杀请求。
-
-
网关层:
-
使用 Nginx 或 Spring Cloud Gateway 做负载均衡和限流。
-
-
服务层:
-
库存预减:在 Redis 中预减库存,避免直接访问数据库。
-
分布式锁:确保库存扣减的原子性。
-
消息队列:将秒杀请求放入消息队列,异步处理订单。
-
-
数据层:
-
Redis:缓存商品库存、秒杀结果。
-
MySQL:存储订单和商品信息,使用事务保证一致性。
-
4. 核心流程
-
初始化数据:
-
将商品库存加载到 Redis 中。
-
设置秒杀开始时间。
-
-
用户请求:
-
用户点击秒杀按钮,前端发送请求到服务端。
-
-
库存预减:
-
服务端从 Redis 中预减库存。
-
如果库存不足,直接返回秒杀失败。
-
-
生成订单:
-
将秒杀请求放入消息队列。
-
异步消费消息,生成订单并写入数据库。
-
-
返回结果:
-
返回秒杀成功或失败的结果给用户。
-
5. 关键代码实现
5.1 Redis 库存预减
java
复制
// 初始化库存 public void initStock(String productId, int stock) { redisTemplate.opsForValue().set("stock:" + productId, stock); } // 预减库存 public boolean reduceStock(String productId) { Long stock = redisTemplate.opsForValue().decrement("stock:" + productId); return stock != null && stock >= 0; }
5.2 分布式锁
java
复制
// 使用 Redis 实现分布式锁 public boolean tryLock(String lockKey, String requestId, int expireTime) { return redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, expireTime, TimeUnit.SECONDS); } // 释放锁 public void releaseLock(String lockKey, String requestId) { if (requestId.equals(redisTemplate.opsForValue().get(lockKey))) { redisTemplate.delete(lockKey); } }
5.3 消息队列处理订单
java
复制
// 发送消息到队列 public void sendOrderMessage(String productId, String userId) { Map<String, String> message = new HashMap<>(); message.put("productId", productId); message.put("userId", userId); rabbitTemplate.convertAndSend("orderQueue", message); } // 消费消息生成订单 @RabbitListener(queues = "orderQueue") public void handleOrderMessage(Map<String, String> message) { String productId = message.get("productId"); String userId = message.get("userId"); // 生成订单并写入数据库 orderService.createOrder(productId, userId); }
5.4 数据库事务
java
复制
@Transactional public void createOrder(String productId, String userId) { // 扣减库存 productService.reduceStock(productId); // 创建订单 Order order = new Order(); order.setProductId(productId); order.setUserId(userId); order.setCreateTime(new Date()); orderMapper.insert(order); }
6. 优化措施
-
限流:
-
使用令牌桶或漏桶算法限制请求流量。
-
使用 Nginx 或网关层限流。
-
-
缓存预热:
-
提前将商品库存加载到 Redis 中,避免秒杀开始时大量请求直接访问数据库。
-
-
队列削峰:
-
使用消息队列异步处理订单,避免系统瞬时压力过大。
-
-
分库分表:
-
对订单表进行分库分表,提高数据库读写性能。
-
-
降级和熔断:
-
使用 Hystrix 或 Sentinel 实现服务降级和熔断,保证系统稳定性。
-
7. 总结
-
通过 Redis 缓存库存、消息队列异步处理、分布式锁等技术,可以有效支持高并发秒杀场景。
-
系统设计需要综合考虑性能、一致性和用户体验,同时做好限流、降级等保护措施。