订单交易简析

1.订单交易流程分析

        订单交易作为涉及到钱的部分势必要谨慎,我们来大体分析一下其中的流程。

        

  1. 检查(把不必要的请求第一时间挡回去)
    1. 检查本地缓存是否售罄
    2. 校验是否有权限购买
    3. 判断redis库存是否充足
    4. 检查是否排队当中
    5. .... ...
  2. 获取产品信息
  3. 验证秒杀或活动时间是否超时
  4. 获取会员信息
  5. 获取会员地址
  6. 预减库存
  7. 生成下单商品信息
  8. 库存处理

下面主要分析一下最重要的1,6和8项。

2.检查

  • 在检查中最主要的就是检查我们redis中的库存是否充足。
private CommonResult confirmCheck(Long productId, Long memberId, String token){
        Integer stock = redisOpsUtil.get(RedisKeyPrefixConst.MIAOSHA_STOCK_CACHE_PREFIX+productId,Integer.class);
        if(stock == null||stock<0){
            return CommonResult.failed("商品已经售罄,请购买其它商品!");
        }
        String async = redisOpsUtil.get(RedisKeyPrefixConst.MIAOSHA_ASYNC_WAITING_PREFIX + memberId + ":" + productId);
        if (async != null && async.equals("1")) {
            Map<String, Object> result = new HashMap<>();
            result.put("orderStatus", "1");//下单方式0->同步下单,1->异步下单排队中,-1->秒杀失败,>1->秒杀成功(返回订单号)
            return CommonResult.failed(result, "异步下单排队中");
        }
        return CommonResult.success(null);
    }

        在此我们发现我们需要先把商品的库存同步到redis中,否则我们在检查的时候就会永远无库存了。

 public void afterPropertiesSet() throws Exception {
        FlashPromotionParam promotion = flashPromotionProductDao.getFlashPromotion(null);
        if (null==promotion){
            return;
        }
        Date now = new Date();
        Date endDate = promotion.getEndDate();//结束时间
        final Long expired = endDate.getTime()-now.getTime();//剩余时间
        promotion.getRelation().stream().forEach((item)->{
            redisOpsUtil().setIfAbsent(
                    RedisKeyPrefixConst.MIAOSHA_STOCK_CACHE_PREFIX + item.getProductId()
                    , item.getFlashPromotionCount()
                    , expired
                    , TimeUnit.MILLISECONDS);
        });
    }

        将库存放入redis中并设置超时时间,活动结束即失效。

  • 本地缓存

        我们都习惯在后端设置本地缓存来减轻redis的压力,同样在库存检测的时候我们怎么设置本地缓存呢?

        当然不需要向redis一样去存库存这样麻烦,我们仅需要一个布尔值的标志位即可,有库存即为true,无库存则为false,如果为false就不在需要去查redis了,即可大大减轻我们redis的负载。但是有一个问题,在集群环境下如何做到同步各节点的数据呢?

        用消息队列进行同步就有点大材小用了,这里推荐两种方式,一种是用zk的watcher机制进行同步,另一种就是利用redis的channel机制了,在这里我们用后者进行实现。 

         首先我们更新下我们上面的代码,加入本地缓存校验的内容

 private CommonResult confirmCheck1(Long productId, Long memberId, String token){
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值