慕课高并发实战,卖超问题压测的时候,秒杀商品库存为0,但是在压测过程中,生成的订单数与秒杀订单数远远超过库存数

1.慕课高并发实战,卖超问题压测的时候,秒杀商品库存为0,但是在压测过程中,生成的订单数与秒杀订单数远远超过库存数

2.Controller层

  @RequestMapping(value = "/do_seckill", method = RequestMethod.POST)
    @ResponseBody
    public Result<OrderInfo> seckill(Model model, SeckillUser seckillUser,
                                        @RequestParam("goodsId") long goodsId){
        model.addAttribute("user", seckillUser);
        if(seckillUser == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        //判断库存
        GoodsVO goods = goodsService.getGoodsByGoodsId(goodsId);//10个商品,req1 req2
        int stock = goods.getStockCount();
        if(stock <= 0) {
            return Result.error(CodeMsg.GOODS_EMPTY);
        }
        //判断是否已经秒杀到了
        SeckillOrder order = orderService.getSeckillOrderByUserIdGoodsId(seckillUser.getId(), goodsId);
        if(order != null) {
            return Result.error(CodeMsg.REPEATE_SECKILL);
        }
        //减库存 下订单 写入秒杀订单
        OrderInfo orderInfo = seckillService.seckill(seckillUser, goods);
        return Result.success(orderInfo);

    }

2.service层
SeckillService

@Transactional
    public OrderInfo seckill(SeckillUser user, GoodsVO goods) {
        //减库存 下订单 写入秒杀订单
        goodsService.reduceStock(goods);
        //order_info sl_order
        return orderService.createOrder(user, goods);
    }

GoodsService

public void reduceStock(GoodsVO goods) {
        SeckillGoods g = new SeckillGoods();
        g.setGoodsId(goods.getId());
        goodsDao.reduceStock(g);
    }

OrderService

 /**
     * 判断该用户是否秒杀成功,从redis中获取
     * @param userId
     * @param goodsId
     * @return
     */
    public SeckillOrder getSeckillOrderByUserIdGoodsId(long userId, long goodsId) {
        //return orderDao.getSeckillOrderByUserIdGoodsId(userId, goodsId);
        return redisService.get(OrderKey.getSeckillOrderByUidGid,""+userId+"_"+goodsId, SeckillOrder.class);
    }

    //下订单 order_info sl_order
    @Transactional
    public OrderInfo createOrder(SeckillUser seckillUser, GoodsVO goodsVO){
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCreateDate(new Date());
        orderInfo.setDeliveryAddrId(0L);
        orderInfo.setGoodsCount(1);
        orderInfo.setGoodsId(goodsVO.getId());
        orderInfo.setGoodsName(goodsVO.getGoodsName());
        orderInfo.setGoodsPrice(goodsVO.getSeckillPrice());
        orderInfo.setOrderChannel(1);
        orderInfo.setStatus(0);
        orderInfo.setUserId(seckillUser.getId());
        long orderId = orderDao.insertOrder(orderInfo);
        SeckillOrder miaoshaOrder = new SeckillOrder();
        miaoshaOrder.setGoodsId(goodsVO.getId());
        miaoshaOrder.setOrderId(orderId);
        miaoshaOrder.setUserId(seckillUser.getId());
        orderDao.insertSeckillOrder(miaoshaOrder);

        redisService.set(OrderKey.getSeckillOrderByUidGid, ""+seckillUser.getId()+"_"+goodsVO.getId(), miaoshaOrder);

        return orderInfo;
    }

    //获取秒杀订单
    public OrderInfo getSeckillOrderById(long orderId) {
        return orderDao.getSeckillOrderById(orderId);
    }

dao层
OrderDao

@Insert("insert into order_info(user_id, goods_id, goods_name, goods_count, goods_price, order_channel, status, create_date)values("
            + "#{userId}, #{goodsId}, #{goodsName}, #{goodsCount}, #{goodsPrice}, #{orderChannel},#{status},#{createDate} )")
    @SelectKey(keyColumn = "id", keyProperty = "id", resultType = long.class, before = false, statement = "select last_insert_id()")
    public long insertOrder(OrderInfo orderInfo);

    @Insert("insert into sl_order(user_id, goods_id, order_id) values (#{userId},#{goodsId},#{orderId})")
    public int insertSeckillOrder(SeckillOrder seckillOrder);

GoodsDao

@Update("update sl_goods set stock_count = stock_count - 1 where goods_id = #{goodsId} and stock_count > 0")
    public int reduceStock(SeckillGoods seckillGoods);

数据库:
在秒杀商品的秒杀表,简历了用户与商品的联合唯一索引
图片说明

麻烦大家帮我解决一下

https://blog.csdn.net/u013871100/article/details/99055708