使用RabbitMQ改写秒杀功能
实现思路
思路:减少数据库访问
具体的实现流程就是
1.系统初始化,把商品库存数量加载到Redis
2.收到请求,Redis预减库存,库存不足,直接返回,否则3
3.请求入队,立即返回排队中
4.请求出队,生成订单,减少库存
5.客户端轮询,是否秒杀成功
其中4和5是同时并发处理的。
具体实现
系统初始化,把商品库存数量加载到Redis
如何在初始化的时候就将库存数据存入缓存中
通过实现InitializingBean接口中的一个方法:afterPropertiesSet()
系统初始化会首先调用该函数:
/**
* 系统初始化会调用该函数
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
List<GoodsVo> goodsVoList = goodsService.listGoodsVo();
if (goodsVoList == null){
return;
}
for (GoodsVo goodsVo:goodsVoList){
//预先把商品库存加载到redis中
redisService.set(GoodsKey.getSeckillGoodsStock,""+goodsVo.getId(),goodsVo.getStockCount());
localOverMap.put(goodsVo.getId(),false);
}
}
收到请求,Redis预减库存,库存不足,直接返回,否则请求入队,立即返回排队中
首先需要一个RabbitMQ的队列
使用Direct交换机模式
/**
* Direct 交换机模式
*/
//队列
@Bean
public Queue secKill_QUEUE() {
return new Queue(SECKILL_QUEUE,true);
}
队列消息的发送
public void sendSecKillMessage(SecKillMessage secKillMessage) {
String msg = RedisService.Bean2String(secKillMessage);
logger.info("send SecKill message: " + msg);
amqpTemplate.convertAndSend(MQConfig.SECKILL_QUEUE, msg);
}
秒杀的实现
//预先减库存
long stock = redisService.decr(GoodsKey.getSeckillGoodsStock,""+goodsId);
if (stock < 0){
localOverMap.put(goodsId,true);
return Result.error(CodeMsg.SECKILL_OVER);
}
//判断是否已经秒杀到了
SecKillOrder order = orderService.getOrderByUse