技术选型与架构设计
采用Spring Boot+MyBatis+MySQL组合,MySQL使用InnoDB引擎支持事务。架构上采用分层设计:
- Web层:接收秒杀请求,进行参数校验
- Service层:核心业务逻辑,处理库存扣减
- DAO层:数据库操作,通过@Transactional注解管理事务
数据库表设计
关键表结构需包含:
CREATE TABLE `seckill_item` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_bin DEFAULT NULL,
`stock` int DEFAULT 0 COMMENT '库存',
`start_time` datetime DEFAULT NULL COMMENT '秒杀开始时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
CREATE TABLE `seckill_order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`item_id` bigint DEFAULT NULL,
`user_id` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_item` (`user_id`,`item_id`) COMMENT '防重复秒杀'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
事务控制实现
采用悲观锁实现库存扣减事务:
@Transactional(rollbackFor = Exception.class)
public boolean handleSeckill(Long itemId, String userId) {
// 1. 查询商品并加锁
SeckillItem item = seckillItemMapper.selectForUpdate(itemId);
// 2. 校验库存
if (item.getStock() <= 0) {
return false;
}
// 3. 扣减库存
seckillItemMapper.reduceStock(itemId);
// 4. 创建订单
SeckillOrder order = new SeckillOrder();
order.setItemId(itemId);
order.setUserId(userId);
seckillOrderMapper.insert(order);
return true;
}
高并发优化方案
Redis缓存预热
活动开始前将库存加载到Redis,通过原子操作扣减:
Long stock = redisTemplate.opsForValue().decrement("seckill:stock:" + itemId);
if (stock < 0) {
// 库存不足时恢复Redis计数
redisTemplate.opsForValue().increment("seckill:stock:" + itemId);
return false;
}
异步下单处理
使用消息队列削峰:
@RabbitListener(queues = "seckill.queue")
public void processSeckillOrder(SeckillMessage message) {
// 异步执行数据库操作
seckillService.createOrder(message.getItemId(), message.getUserId());
}
事务隔离级别配置
在application.properties中设置:
spring.datasource.tomcat.default-transaction-isolation=2 # READ_COMMITTED
异常处理机制
自定义异常类处理业务异常:
public class SeckillException extends RuntimeException {
public SeckillException(String message) {
super(message);
}
}
@Transactional(rollbackFor = SeckillException.class)
public void seckillOperation() throws SeckillException {
// 业务代码...
}
600

被折叠的 条评论
为什么被折叠?



