Java并发编程实战:高并发秒杀系统设计与实现
一、系统架构设计
本秒杀系统采用分层架构设计:
- 接入层:Nginx负载均衡 + 限流
- 应用层:SpringBoot微服务集群
- 缓存层:Redis集群 + 分布式锁
- 消息队列:RabbitMQ异步削峰
- 数据层:MySQL分库分表
二、核心代码实现
1. 分布式锁实现
public class RedisDistributedLock {
private final StringRedisTemplate redisTemplate;
private final String lockKey;
private final String lockValue;
private final long expireTime;
public RedisDistributedLock(StringRedisTemplate redisTemplate,
String lockKey, long expireTime) {
this.redisTemplate = redisTemplate;
this.lockKey = lockKey;
this.lockValue = UUID.randomUUID().toString();
this.expireTime = expireTime;
}
public boolean tryLock() {
return redisTemplate.opsForValue()
.setIfAbsent(lockKey, lockValue, expireTime, TimeUnit.MILLISECONDS);
}
public boolean unlock() {
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),
Collections.singletonList(lockKey),
lockValue
);
return result != null && result == 1;
}
}
2. 秒杀核心逻辑
@Service
public class SeckillService {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;
public Result seckill(long userId, long goodsId) {
// 1. 校验秒杀状态
Boolean isSeckill = redisTemplate.opsForValue()
.getBit("seckill:goods:" + goodsId, userId);
if (isSeckill != null && isSeckill) {
return Result.error("请勿重复秒杀");
}
// 2. 预减库存
Long stock = redisTemplate.opsForValue()
.decrement("seckill:stock:" + goodsId);
if (stock == null || stock < 0) {
return Result.error("秒杀已结束");
}
// 3. 生成订单
SeckillOrder order = new SeckillOrder();
order.setUserId(userId);
order.setGoodsId(goodsId);
// 4. 异步处理
rabbitTemplate.convertAndSend(
"seckill.order.exchange",
"seckill.order.routingKey",
order
);
// 5. 标记已参与
redisTemplate.opsForValue()
.setBit("seckill:goods:" + goodsId, userId, true);
return Result.success("秒杀成功");
}
}
三、高并发优化方案
1. 缓存预热
@PostConstruct
public void initSeckillGoods() {
List goodsList = goodsMapper.selectAll();
goodsList.forEach(goods -> {
String stockKey = "seckill:stock:" + goods.getId();
redisTemplate.opsForValue().set(stockKey, goods.getStock());
});
}
2. 库存分段优化
public Result seckill(long userId, long goodsId) {
// 分段获取库存key
int segment = (int) (userId % 10);
String stockKey = "seckill:stock:" + goodsId + ":" + segment;
// 其他逻辑不变...
}
四、安全防护措施
- 接口限流:Guava RateLimiter实现
- 验证码:防止机器人刷单
- 隐藏秒杀地址:动态生成URL
- 数据校验:前端+后端双重校验
- 防脚本作弊:用户行为分析
五、性能测试指标
优化措施 | QPS提升 | 响应时间 |
---|---|---|
原始方案 | 500 | 800ms |
+Redis缓存 | 2000 | 200ms |
+消息队列 | 5000 | 100ms |
+库存分段 | 8000+ | 50ms |