java吧 关注:1,252,792贴子:12,738,431
  • 1回复贴,共1

商城项目秒杀模块问题,面试时被问到的

取消只看楼主收藏回复

为啦防止用户重复购买,需要判断用户是否已经购买过啦,但是如果同一时间一个用户发出两次请求,这时判断都是未购买,这种问题怎么办


IP属地:山东1楼2019-01-06 14:20回复
    @Override//保存秒杀订单
    public void saveSeckillOrder(Long seckillGoodsId, String userId) {
    //有请求下单的任务,就把排队人数加一
    redisTemplate.boundValueOps("SECKILL_COUNT_ORDER_QUEUE").increment(1);
    //判断该用户是否已经秒杀过啦
    Boolean member = redisTemplate.boundSetOps("SECKILL_PAY_LOG" + seckillGoodsId).isMember(userId);
    if (member) {
    throw new RuntimeException("请先支付,不允许重复秒杀");
    }
    //解决超卖问题 task里leftpush 这里rightpop [3,2,1]
    Object o = redisTemplate.boundListOps("SECKILL_GOODS_QUEUE" + seckillGoodsId).rightPop();
    if (o == null) {
    throw new RuntimeException("被抢光啦");
    }
    TbSeckillGoods seckill_goods = (TbSeckillGoods) redisTemplate.boundHashOps("SECKILL_GOODS").get(seckillGoodsId);
    //判断是否有库存
    if (seckill_goods.getStockCount() <= 0 || seckill_goods == null) {
    throw new RuntimeException("被抢光啦");
    }
    //当排队人数过多时,提示
    Long count_order_queue = redisTemplate.boundValueOps("SECKILL_COUNT_ORDER_QUEUE").size();
    if (count_order_queue > (seckill_goods.getStockCount() + 10)) {
    throw new RuntimeException("当前人数过多");
    }
    //将多线程操作mysql任务放入redis
    redisTemplate.boundListOps("SECKILL_ORDER_QUEUE").leftPush(new UserIdAndSeckillGoodsId(userId, seckillGoodsId));
    executor.execute(createOrder);
    }


    IP属地:山东3楼2019-01-06 16:08
    回复