当前位置: 首页 > news >正文

建湖网站设计最新网站建设进程

建湖网站设计,最新网站建设进程,新宾区网站建设,抖音seo推荐算法库存超卖问题分析 库存超卖问题其本质就是多个线程操作共享数据产生的线程安全问题,即当一个线程在执行操作共享数据的多条代码的过程中,其他线程也参与了进来,导致了线程安全问题的产生。例如:线程1发送请求,查询库存…

库存超卖问题分析

库存超卖问题其本质就是多个线程操作共享数据产生的线程安全问题,即当一个线程在执行操作共享数据的多条代码的过程中,其他线程也参与了进来,导致了线程安全问题的产生。例如:线程1发送请求,查询库存,发现库存大于1,在还没来及扣除库存时,线程2甚至线程3等发送请求,发现这个数量也是大于1,那么这多个线程都会去扣除库存,最终多个线程都去扣除库存,此时就会出现库存的超卖问题。

image-20230707172612925
image-20230707172612925
  • 多线程安全问题常见的解决方案就是加锁

    • 悲观锁:认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行,synchronized、lock都属于悲观锁,属于同步锁,让线程串行执行,优点是简单粗暴,缺点是性能一般
    • 乐观锁:认为线程安全问题不一定会发生,只是在更新数据时,判断有没有其他线程对数据做了修改,优点是性能好,缺点是存在成功率问题
      • 如果没有修改,则认为是安全的,该线程进行数据更新
      • 如果已经被其他线程修改,则发生了线程安全问题,此时可以重试或异常
  • 使用乐观锁解决库存超卖问题

    • 乐观锁的关键是判断之前查询得到的数据是否被修改过,常见的方式有两种

      • 版本号法

        • 在数据库等中设置一个版本号字段,每次操作数据会对版本号进行加一操作,当每次读取数据时,读出版本号字段 ,在修改数据的时候,需要判断读出的版本号和数据库是否一致,如果一致,则表明在自己操作该数据的过程中,没有其他线程操作该数据,如果版本号不一致,则表明数据以及被别人修改过了。

          image-20230710111424101
          image-20230710111424101
      • CAS

        • 在扣减库存时,将现在库存和之前查询的库存做对比,如果一样,则说明没有其他线程在中间修改过库存数据,则认为是线程安全的,如果不一样,则说明有线程在中间修改过库存数据。

          image-20230710143222845
          image-20230710143222845

乐观锁解决超卖问题

  • 使用在扣减库存时,将现在库存和之前查询的库存做对比,如果一样,则表明没有人在此中间修改过库存,则认定线程安全,扣除库存

    @Override
    public Long seckillVoucher(Long voucherId) {

        // 查询秒杀优惠券信息
        SeckillVoucher seckillVoucher = seckillVoucherService.getById(voucherId);
        //判断秒杀是否开始和结束
        LocalDateTime beginTime = seckillVoucher.getBeginTime();
        LocalDateTime endTime = seckillVoucher.getEndTime();
        //如果当前时间 在开始时间之后 再结束时间之前 则表明秒杀能进行
        LocalDateTime localDateTime = LocalDateTime.now();
        if ( localDateTime.isBefore(beginTime) || localDateTime.isAfter(endTime) ){
            return null;
        }
        //获取库存量
        Integer stock = seckillVoucher.getStock();
        if (ObjectUtil.isNull(stock) || ObjectUtil.isNotNull(stock) && stock.intValue() <= 0){
            return null;
        }
        //扣减库存 将现在库存和之前查询的库存做对比,如果一样,则表明没有人在此中间修改过库存,则认定线程安全,扣除库存
        boolean update = seckillVoucherService.update(
                new LambdaUpdateWrapper<SeckillVoucher>().setSql("stock = stock - 1").eq(SeckillVoucher::getVoucherId, voucherId)
                        .eq(SeckillVoucher::getStock, stock)
        );
        if (!update){
            return null;
        }
        //创建订单
        VoucherOrder voucherOrder = new VoucherOrder();
        //创建订单ID
        long orderId = redisIdWorker.nextId("order");
        voucherOrder.setId(orderId);
        //获取用户ID
        Long id = UserHolder.getUser().getId();
        voucherOrder.setUserId(id);
        // 代金券id
        voucherOrder.setVoucherId(voucherId);
        this.save(voucherOrder);
        return orderId;
    }

    该方式通过测试能够发现,失败率很高,这主要是由于当多个人都拿到库存时,只有一个能够扣减成功,其他的由于.eq(SeckillVoucher::getStock, stock)无法完成扣减。

    其实在超卖问题中,我们需要保证的是在没用库存的情况下,不能再进行库存扣减,所有需要保证的是库存大于0,所有可以设置.gt(SeckillVoucher::getStock, 0)

    @Override
    public Long seckillVoucher(Long voucherId) {

        // 查询秒杀优惠券信息
        SeckillVoucher seckillVoucher = seckillVoucherService.getById(voucherId);
        //判断秒杀是否开始和结束
        LocalDateTime beginTime = seckillVoucher.getBeginTime();
        LocalDateTime endTime = seckillVoucher.getEndTime();
        //如果当前时间 在开始时间之后 再结束时间之前 则表明秒杀能进行
        LocalDateTime localDateTime = LocalDateTime.now();
        if ( localDateTime.isBefore(beginTime) || localDateTime.isAfter(endTime) ){
            return null;
        }
        //获取库存量
        Integer stock = seckillVoucher.getStock();
        if (ObjectUtil.isNull(stock) || ObjectUtil.isNotNull(stock) && stock.intValue() <= 0){
            return null;
        }
        //扣减库存 将现在库存和之前查询的库存做对比,如果一样,则表明没有人在此中间修改过库存,则认定线程安全,扣除库存
        boolean update = seckillVoucherService.update(
                new LambdaUpdateWrapper<SeckillVoucher>().setSql("stock = stock - 1").eq(SeckillVoucher::getVoucherId, voucherId)
                        .gt(SeckillVoucher::getStock, 0)
        );
        if (!update){
            return null;
        }
        //创建订单
        VoucherOrder voucherOrder = new VoucherOrder();
        //创建订单ID
        long orderId = redisIdWorker.nextId("order");
        voucherOrder.setId(orderId);
        //获取用户ID
        Long id = UserHolder.getUser().getId();
        voucherOrder.setUserId(id);
        // 代金券id
        voucherOrder.setVoucherId(voucherId);
        this.save(voucherOrder);
        return orderId;
    }

本文由 mdnice 多平台发布

http://www.yayakq.cn/news/436995/

相关文章:

  • 晋城网站建设费用多用户旅游网站开发
  • 图书馆网站建设的建议常见的网站模式
  • 如何建设自己的企业网站专业建站公司
  • 网站设计稿是怎么做的外贸网站建设定制开发
  • 南昌网站建设培训班软件技术专升本
  • dedecms可以做双语网站小孩子和大人做的网站
  • 郑州高端网站定制公司珠海网站建设公
  • 心理健康教育网站建设网上申请开办公司流程
  • 找别人做网站一定注意什么宁波网站推广制作
  • 口碑好网站建设在哪里网站建设对公司来说重要吗
  • 做基础销量的网站如何做摄影网站
  • 中国建设银行福州招聘信息网站安徽省交通建设股份有限公司网站
  • 做智能网站系统下载软件用自己电脑做主机做网站
  • 怎么看网站开发语言信息台山网站建设公司
  • 苏州制作网页找哪家网站优化的核心不包括
  • 建设一个大型电影网站大型网站如何开发
  • 怎么做自己的网站人防工程做资料的网站
  • 福州房产网站建设wordpress安装乱码
  • 贵州建设厅网站报名系统设计之家素材
  • 临时网站搭建网站收录慢
  • 网站建设怎么加音乐响应式网站和自适应
  • 企业网站建站程序在线登录qq聊天入口
  • 网站充值怎么做的惠州网站制作公司
  • 聊城企业网站建设长清做网站
  • soho做网站银川建设网站
  • 韩国教育网站模板dw旅游网站怎么做
  • 做一个网站做少钱廊坊网站制作推广
  • 快速网站开发框架手机网站模板 源码
  • 沈阳三好街附近做网站网站开发有哪些书籍
  • 门户网站域名是什么意思请问哪个网站可以做当地向导