文章只展示部分核心代码,完整代码请参考源码
1. 系统初始化,把商品库存数量加载到Redis
public void afterPropertiesSet() throws Exception {List<GoodsVo> goodsList = goodsService.listGoodsVo();if (goodsList == null){return;}for (GoodsVo goods : goodsList) {redisService.set(GoodsKey.getMiaoshaGoodsStock,""+goods.getId(),goods.getStockCount());localOverMap.put(goods.getId(),false);}}
2.内存标记减少Redis访问
private Map<Long,Boolean> localOverMap = new HashMap<Long, Boolean>();boolean over = localOverMap.get(goodsId);if (over){return Result.error(CodeMsg.MIAO_SHA_OVER);}
收到请求,Redis预减库存,库存不足,直接返回,否则进入4
Long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, "" + goodsId);if (stock < 0){localOverMap.put(goodsId,true);//标记return Result.error(CodeMsg.MIAO_SHA_OVER);}
3. 请求入队缓存,异步下单,立即返回排队中
//入队MiaoshaMessage mm = new MiaoshaMessage();mm.setUser(user);mm.setGoodsId(goodsId);sender.sendMiaoshaMessage(mm);return Result.success(0);//排队中
4. 请求出队,生成订单,减少库存
@RabbitListener(queues=MQConfig.MIAOSHA_QUEUE)public void receive(String message) {log.info("receive message:"+message);MiaoshaMessage mm = RedisService.stringToBean(message, MiaoshaMessage.class);MiaoshaUser user = mm.getUser();long goodsId = mm.getGoodsId();GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);int stock = goods.getStockCount();if(stock <= 0) {return;}//判断是否已经秒杀到了MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);if(order != null) {return;}//减库存 下订单 写入秒杀订单miaoshaService.miaosha(user, goods);}
5. 客户端轮询,是否秒杀成功
```javascript success:function(data){ if(data.code == 0){
var result = data.data;if (result < 0) {layer.msg("对不起,秒杀失败");}else if (result == 0) {//继续轮询setTimeout(function () {getMiaoshaResult(goodsId);},50);}else {layer.confirm("恭喜你秒杀成功!查看订单?",{btn:["确定","取消"]},function () {window.location.href="/order_detail.htm?orderId="+result;},function () {layer.closeAll();});}
}else{
layer.msg(data.msg);} },
function getMiaoshaResult(goodsId) { g_showLoading(); $.ajax({ url:”/miaosha/result”, type:”GET”, data:{ goodsId:$(“#goodsId”).val(), }, success:function(data){ if(data.code == 0){ var result = data.data; if (result < 0) { layer.msg(“对不起,秒杀失败”); }else if (result == 0) {//继续轮询 setTimeout(function () { getMiaoshaResult(goodsId); },50); }else { layer.confirm(“恭喜你秒杀成功!查看订单?”,{btn:[“确定”,”取消”]}, function () { window.location.href=”/order_detail.htm?orderId=”+result; }, function () { layer.closeAll(); }); } }else{ layer.msg(data.msg); } }, error:function(){ layer.msg(“客户端请求有误”); } }); } ```
