zoukankan      html  css  js  c++  java
  • 秒杀代码核心部分

      //内存标记,商品是否卖完
        private HashMap<Long, Boolean> localOverMap =  new HashMap<Long, Boolean>();
        
        /**
         * 系统初始化,加载商品库存,并为每个商品初始化内存标记
         * */
        public void afterPropertiesSet() throws Exception {  //该Controller实现InitializingBean
            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);
            }
        }
        
        //这里使用pathVariable,为了拼接动态路径,也是一种防刷手段
       @RequestMapping(value
    ="/{path}/do_miaosha", method=RequestMethod.POST) @ResponseBody public Result<Integer> miaosha(Model model,MiaoshaUser user, @RequestParam("goodsId")long goodsId, @PathVariable("path") String path) { model.addAttribute("user", user); if(user == null) { return Result.error(CodeMsg.SESSION_ERROR); } //验证path boolean check = miaoshaService.checkPath(user, goodsId, path); if(!check){ return Result.error(CodeMsg.REQUEST_ILLEGAL); } //内存标记,减少redis访问,如果没有这一步,也可以,直接去预减库存,但是,会造成redis的负担,所以加一个非线程安全的map,去做一层简单过滤 //同一时间,有可能100个人去抢最后一件商品(get为false),但是没关系,有redis的decr去做原子保障,保证不会超卖 boolean over = localOverMap.get(goodsId); if(over) { return Result.error(CodeMsg.MIAO_SHA_OVER); }
         //开始主流程:预减库存->判断重复秒杀->加入消息队列,返回成功(即排队中)
    //预减库存 long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, ""+goodsId);//10 if(stock < 0) { localOverMap.put(goodsId, true); redisService.set(GoodsKey.getMiaoshaGoodsStock, ""+goodsId,0); return Result.error(CodeMsg.MIAO_SHA_OVER); } //判断是否已经秒杀到了 //redisService.set(OrderKey.getMiaoshaOrderByUidGid, ""+user.getId()+"_"+goods.getId(), miaoshaOrder); MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId); if(order != null) { redisService.incr(GoodsKey.getMiaoshaGoodsStock, ""+goodsId); localOverMap.put(goodsId, false); return Result.error(CodeMsg.REPEATE_MIAOSHA); } //入队 MiaoshaMessage mm = new MiaoshaMessage(); mm.setUser(user); mm.setGoodsId(goodsId);
         //消息队列发送者,发送消息 sender.sendMiaoshaMessage(mm);
    return Result.success(0);//排队中,用户点击秒杀后(内部去请求path,然后用path去请求秒杀服务,然后调轮询接口,查询结果) } /**做延迟任务setTimeOut,轮询秒杀结果 * orderId:成功 * -1:秒杀失败 * 0: 排队中 * */ @RequestMapping(value="/result", method=RequestMethod.GET) @ResponseBody public Result<Long> miaoshaResult(Model model,MiaoshaUser user, @RequestParam("goodsId")long goodsId) { model.addAttribute("user", user); if(user == null) { return Result.error(CodeMsg.SESSION_ERROR); } long result =miaoshaService.getMiaoshaResult(user.getId(), goodsId); return Result.success(result); } @AccessLimit(seconds=5, maxCount=5, needLogin=true)//自定义注解,接口防刷 @RequestMapping(value="/path", method=RequestMethod.GET)//先获取path,才能请求秒杀接口 @ResponseBody public Result<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user, @RequestParam("goodsId")long goodsId, @RequestParam(value="verifyCode", defaultValue="0")int verifyCode ) { if(user == null) { return Result.error(CodeMsg.SESSION_ERROR); } boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode); if(!check) { return Result.error(CodeMsg.REQUEST_ILLEGAL); } String path = miaoshaService.createMiaoshaPath(user, goodsId); return Result.success(path); } }
  • 相关阅读:
    GhostBSD 3.0RC3,基于GNOME的FreeBSD
    Nagios 3.4.3 发布,企业级监控系统
    Jolokia 1.0.6 发布, JMX远程访问方法
    微软希望开发人员不要使 WebKit 成为新版 IE6
    Kwort Linux 3.5 正式版发布
    EJDB 1.0.24 发布,嵌入式 JSON 数据库引擎
    Pale Moon 15.3 Firefox“苍月”优化版发布
    Galera Load Balancer 0.8.1 发布
    SmartSVN V7.5 正式发布
    PostgresQL建立索引如何避免写数据锁定
  • 原文地址:https://www.cnblogs.com/brxHqs/p/9766820.html
Copyright © 2011-2022 走看看