java吧 关注:1,215,809贴子:12,663,324
  • 14回复贴,共1

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

只看楼主收藏回复

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


IP属地:山东1楼2019-01-06 14:20回复
    规定时间内只能发出一次请求,其他直接返回。。。,csdn秒杀问题总结很多


    来自Android客户端2楼2019-01-06 16:00
    回复
      @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
      回复
        你是哪个黑马的,我是上海的。


        IP属地:安徽来自Android客户端4楼2019-01-06 16:27
        回复
          使用同步,在将用户加入购买列表的代码放到同步块里面执行,加入前先判断购买列表里有没有该用户
          synchronized(this.getClass){
          Boolean member = redisTemplate.boundSetOps("SECKILL_PAY_LOG" + seckillGoodsId).isMember(userId);
          if (member) {
          throw new RuntimeException("请先支付,不允许重复秒杀");
          }
          //将多线程操作mysql任务放入redis
          redisTemplate.boundListOps("SECKILL_ORDER_QUEUE").leftPush(new UserIdAndSeckillGoodsId(userId, seckillGoodsId));
          executor.execute(createOrder);
          }


          IP属地:四川5楼2019-01-06 21:31
          回复(3)
            直接在表里加一个字段和userid关联代表是否购买,执行购买的时候sql必须加上where 是否购买=否


            IP属地:四川来自Android客户端6楼2019-01-07 12:38
            回复
              锁机制了解下!


              7楼2019-01-07 12:44
              回复
                同一用户同一时间怎么发出2次请求?


                IP属地:陕西8楼2019-01-07 13:08
                回复
                  分布式锁呀,下单时候需要加锁,你可以理解为下单必须是串行的,加锁期间判断这个用户是不是秒杀过,秒杀


                  IP属地:四川9楼2019-05-30 14:27
                  回复
                    楼楼,你这头像吓我一跳哦


                    IP属地:浙江10楼2019-08-25 16:49
                    回复
                      滴滴


                      来自iPhone客户端11楼2022-08-06 08:37
                      回复