• 43、优惠券秒杀(超卖问题分析(乐观锁解决思路))


    优惠券秒杀(超卖问题分析(乐观锁解决思路))

    超卖问题(多线程):

    想象一下线程1先查询数据库为1,然后卖出去了准备-1,在这期间有其他线程进来也查询库存(此时线程1进行扣减库存)所以查到的也是1,那么这这些线程都进行扣减库存操作(在这些个其他线程中他们的逻辑是没有问题的,但是我们的库存就一直在进行扣减操作了,出现了超卖)

     

    逻辑有问题

     

    解决思路:加锁(悲观锁还是乐观锁呢?乐观锁的性能更好点这里使用乐观锁)

     

    1、!!!悲观锁:认为线程一定会出问题,所以在我们操作数据之前一定要先获取锁,确保线程串行执行咯(例如我们在多线程学到的排它锁啊:Synchronized还有Lock都是悲观锁)

    2、!!!乐观锁:认为线程安全问题不一定发生,在操作数据之前不会直接给线程加锁,而是在修改完数据准备更新的时候去判断数据是否被修改过(判断数据是否被修改是重点哦)

    其中判断没有被修改就认为是安全的,更新数据。判断被修改了,就不更新数据。重试或者抛出异常。

    乐观锁操作:

    1. 版本号法(维护一个版本号标志(每次修改库存版本号都要改变(例如+1)),来判断库存是否被修改过)

    注意:我们的乐观锁操作就是在更改库存的sql语句中在我们不仅要进行库存的扣减,版本号的+1更改,其中还有判断版本跟上面我们查询到的库存版本号和我们的数据的版本是否一致。

    这样我们说下流程吧:

    1. 我们先查新数据库的库存和版本号,分别为1,1。
    2. 我们接着卖了,进行库存的扣减(更新库存),这时我们还要有判断条件sql(where不止是id为10,还有我们的库存为前面查到的1。(他会自己去数据库比对版本号的))
    3. 在我们1、查询库存和版本号还没更新库存的时候,另一线程进来了查询了库存和,版本号为1,1。满足(库存-1,版本号+1)
    4. 接着这个线程也跟着卖了库存-1。他的sql也是id=10和版本为1(他要去改的是id为10和版本为1共同满足的数据(库存))但是他在准备更新的时候其中也要数据库查版本号,一看版本为2(前面的版本号+1变为2了)不成立。不更新(没卖出去ok)。(这里我么一个操作的时间大概是相同的所以不必担心我们这个更新库存的时候版本号还没有修改(也就是第二次的查询能再第一次的更新前,但是其中的第二次更新一定是在第一次更新后的))666别想太多

     

    Cas方案(C:比较,A:and,s:select。先比较再修改)

    !!!也就是优化版本号法(我们用库存来代替版本(我们前面查询的库存如果和我后面查询的库存一样那么一样证明这个库存没有被修改了,线程安全(修改库存)))

    这里我们再说下流程吧:

    1. 和上面的版本号法差不多只是没有了版本号我们的and条件为库存了。我们的sql语句查询的库存必和上面查询库存一样。上面查出的是1那么下面的条件也要是1.满足id为10和库存为1才能修改(数据库一查ok的库存-1变为0)
    2. 第二次我们再中间查的库存还是1,所以我们的sql语句的库存是1才能修改库存,但是他到数据库一查(id为10,库存已经变为0了)。不满足就无法扣减库存咯(没卖出去)over

     

  • 相关阅读:
    微信小程序关键词排名优化:提升你的小程序可见性
    《分布式服务架构:原理,设计与实战》
    新手python的自学总结(已拿到百度offer)
    JavaScript高阶班之ES6 → ES11(八)
    treap平衡树模板
    java计算机毕业设计web开发数码产品推荐平台系统设计与实现源码+mysql数据库+系统+lw文档+部署
    初识EFCore
    回文 马蹄集
    将按顺序表存储的数组转化为链式二叉树并且按照先序、中序、后序排列分别输出
    TiUP 镜像参考指南
  • 原文地址:https://blog.csdn.net/logtcm4/article/details/127732755