北仑建网站价格,用户浏览网站的方式,wordpress手机验证码插件,新艾尚网站建设推广Redis秒杀超卖问题 前言一、出现秒杀超卖的原因二、超卖解决方案使用乐观锁解决超卖问题程序中进行解决 前言
这是我认为b站上最好的redis教程#xff0c;各方面讲解透彻#xff0c;知识点覆盖比较全。 黑马redis视频链接#xff1a;B站黑马redis教学视频 本文参考黑马redi… Redis秒杀超卖问题 前言一、出现秒杀超卖的原因二、超卖解决方案使用乐观锁解决超卖问题程序中进行解决 前言
这是我认为b站上最好的redis教程各方面讲解透彻知识点覆盖比较全。 黑马redis视频链接B站黑马redis教学视频 本文参考黑马redis课程笔记 一、出现秒杀超卖的原因
超卖问题分析 在我们原有代码中是这么写的 if (voucher.getStock() 1) {// 库存不足return Result.fail(库存不足);}//5扣减库存boolean success seckillVoucherService.update().setSql(stock stock -1).eq(voucher_id, voucherId).update();if (!success) {//扣减库存return Result.fail(库存不足);}假设线程1过来查询库存判断出来库存大于1正准备去扣减库存但是还没有来得及去扣减此时线程2过来线程2也去查询库存发现这个数量一定也大于1那么这两个线程都会去扣减库存最终多个线程相当于一起去扣减库存此时就会出现库存的超卖问题。
超卖原因流程图 二、超卖解决方案
超卖问题是典型的多线程安全问题针对这一问题的常见解决方案就是加锁而对于加锁我们通常有两种解决方案 由于加入悲观锁他认为安全问题一定发生所以一定会获取锁进行串行执行这样程序的性能跟吞吐量等受到很大的影响效率大大降低不到万不得已不使用悲观锁
使用乐观锁解决超卖问题
乐观锁 会有一个版本号每次操作数据会对版本号1再提交回数据时会去校验是否比之前的版本大1 如果大1 则进行操作成功这套机制的核心逻辑在于如果在操作过程中版本号只比原来大1 那么就意味着操作过程中没有人对他进行过修改他的操作就是安全的如果不大1则数据被修改过当然乐观锁还有一些变种的处理方式比如cas
程序中进行解决
我们进行扣减库存时加入判断
boolean success seckillVoucherService.update().setSql(stock stock -1) //set stock stock -1.eq(voucher_id, voucherId).eq(stock,voucher.getStock()).update(); //where id and stock ?以上逻辑的核心含义是只要我扣减库存时的库存和之前我查询到的库存是一样的就意味着没有人在中间修改过库存那么此时就是安全的但是以上这种方式通过测试发现会有很多失败的情况失败的原因在于在使用乐观锁过程中假设100个线程同时都拿到了100的库存然后大家一起去进行扣减但是100个人中只有1个人能扣减成功其他的人在处理时他们在扣减时库存已经被修改过了所以此时其他线程都会失败.
通俗一点将 如果100个线程同时开始进行库存的扣减只有一个线程在拿到100库存这时他查询得到的是100我扣减时候的库存是100它可以完美运行这时候库存变成99剩下的99个线程开始扣减时他们一开始拿到的是库存是100扣减时发现库存变成了99所以肯定就不会扣减这样异常率就会特别高
修改上面的判断条件 之前的方式要修改前后都保持一致但是这样我们分析过成功的概率太低所以我们的乐观锁需要变一下改成stock大于0 即可
boolean success seckillVoucherService.update().setSql(stock stock -1).eq(voucher_id, voucherId).update().gt(stock,0); //where id ? and stock 0