文章目录
一、乐观锁的基本概念
乐观锁适用于写少读多的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量
乐观锁实现方式通常有两种 1是通过mybaits配置version版本号的方式 2是通过数据库中根据更新时间使用时间戳的方式
二、讲解下乐观锁失效和成功的场景问题
1.乐观锁失效的场景:
先说下下面这段代码的简单执行流程:
因为是自己的本地去执行 没办法去实现分布式项目运行的整个过程 所以也只能模拟执行流程 但是大体执行过程是不变的
下面是给大家演示的乐观锁失效的过程
因为项目是分布式项目 本人暂时模拟不了线上的环境所以只能以自己模拟的方式给大家展示(1乐观锁失效的场景)
模拟剩余库存数:
项目中的执行代码如下:
1 首先这段代码要开启事务
2 模拟分布式并发下两台机器同时请求查询库存的情况
3 两台服务器同时查找到了相同数据 相当于下面这个goodsSkus集合存储了两条相同的数据(并发查找到)
4 查找到的库存数都为1也就是我们数据库里面的库存数剩为1的库存(这个很重要都拿到了最后一个商品)
5 接下来都做库存减1操作 那么每条数据执行完都是用自己拿到的库存为1的值 进行减1操作 所以两天数据分别执行后库存都为0
6 那么根据乐观锁的定义就是说
1.如果第一条数据根据id和版本号执行完修改操作后版本号就会加1
2.第二条数据根据id和版本号在去更新会失败 所以第二条的rsult应该为false 这样才符合正常扣减库存 不出现超卖的现象
7 结论 两条数据的result 都为true 所以说库存扣减一次的情况下有两单商品下单成功了 也就是说这就是乐观锁下出现的库存超卖的问题
上面代码运行完的结果如下图都成功了也就是出现了超卖问题
数据库中的库存数为:
2.乐观锁生效的场景(去掉事务)
模拟剩余库存数
和乐观锁失效场景不同的是 下面开发测试的这段代码去掉了事务 过程和上面乐观锁失效代码是一样的 (除了没有事务) 但是执行结果会有差异哦!
来看下最后的执行结果 第一条执行的结果为ture 也就是修改成功 第二条执行的结果为false 也就是执行修改失败了 那么和我们的预期是相符合的下单没有出现超卖的现象 结果和我们预想的是一样的 开启事务在分布式项目并发下单下 会出现库存超卖的问题 最后使用乐观锁尽量不要在事务下使用并发下会有问题哦
最后看下数据库更新的结果为下图 库存已经更新为0了
3.简单讲解下悲观锁中的排它锁for update行锁的方式防止分布式并发下同时修改同一条数据的问题
首先开启事务
两条请求同时打进来的情况下 使用for update查询 第一条请求会正常执行 第二条请求会等待一条请求执行完提交事务后在继续执行(使用的是数据库行锁的方式执行)看下代码的简单执行过程
这面的这段代码使用了数据库行锁的方式去执行 解决了分布式项目并发下 库存超卖的问题 有兴趣的小伙伴可以自己了解操作下 这里我就不过多说明了我有一篇关于 fou update排它锁的问题感兴趣的小伙伴可以自己去看看
总结
在这篇文章中我主要为大家讲解了分布式项目并发下库存超卖的问题 并且都是自己的亲身经历有问题的小伙伴可以自己去看下 喜欢的话就给个关注加点赞转发哈