流量削峰技术

改进的点

  • 之前的秒杀下单接口被脚本不停的刷
  • 秒杀验证逻辑和秒杀下单接口强关联,代码冗余度高
  • 秒杀验证逻辑复杂,对交易系统产生无关联复杂

在这里插入图片描述

秒杀令牌

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


  //申城秒杀令牌
    //校验用户以及商品
    @Override
    public String generateSecondKillToken(Integer promoId,Integer itemId,Integer userId) {
        //获取对应商品的秒杀活动信息
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);

        //dataobject->model
        PromoModel promoModel = convertFromDataObject(promoDO);
        if(promoModel == null){
            return null;
        }

        //判断当前时间是否秒杀活动即将开始或正在进行,若不是无法生成令牌
        if(promoModel.getStartDate().isAfterNow()){
            promoModel.setStatus(1);
        }else if(promoModel.getEndDate().isBeforeNow()){
            promoModel.setStatus(3);
        }else{
            promoModel.setStatus(2);
        }


        //
        //使用缓存校验itemModel
        ItemModel itemModel = itemService.getItemByIdInCache(itemId);
        if(itemModel == null){
                return null;
        }

        //判断用户是否存在
        UserModel userModel = userService.getUserByIdInCache(userId)

        if(userModel == null){
            return null;
        }


        //生成tockey存入redis内,并给一个5分钟的有效期
        if(promoModel.getStatus().intValue()!=2){
            return null;
        }else{

            //获取秒杀大闸的count数量
           long result = redisTemplate.opsForValue().increment("promo_door_count_" + promoId,-1);
            if(result<0) return  null;


            //生成一个秒杀令牌
            String token = UUID.randomUUID().toString().replace("-","");
            redisTemplate.opsForValue().set("promo_token_"+promoId+"_userid_"+userId+"_itemid_"+itemId,token);
            redisTemplate.expire("promo_token_"+promoId+"_userid_"+userId+"_itemid_"+itemId,5, TimeUnit.MINUTES);
            return token;
        }
    }

在这里插入图片描述

秒杀大闸

在这里插入图片描述


//限制秒杀令牌的数量:多少个用户可以获取到秒杀令牌
 //将秒杀大闸限制到redis内
        redisTemplate.opsForValue().set("promo_door_count_"+promoId,itemModel.getStock().intValue()*4); 

在这里插入图片描述
在这里插入图片描述

队列泄洪(拥塞窗口)

在这里插入图片描述

在orderController中有用户下单时,使用线程池,从线程池中选取线程进行操作,每次最多有20个用户可以进行下单的操作



        //同步调用线程池的submit方法
        //同步调用线程池的subnmit方法
        //拥塞窗口为20的等待队列,用来队列化泄洪
       Future<Object> future =  executorService.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                //加入库存流水init状态
                String stockLogId = itemService.initStockLog(itemId,amount);

                if(!mqProducer.transactionAsyncReduceStock(userModel.getId(),promoId,itemId,amount,stockLogId)){
                    throw new BusinessException(EmBusinessError.UNKNOWN_ERROR,"下单失败");
                }

                return null;
            }
        });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值