一、引言

  随着业务量的增加,单机部署已经无法满足日常需求了,我们可能会把代码部署到多台服务器上去来进行服务的扩容,也就是负载均衡,那在这种场景下,怎么能实现锁的概念呢?

  那么我们知道如果是一台主机部署的话,我们有很多方式可以实现锁的概念,比如利用synchronized关键字实现同步,或者使用reentrantLock可重入锁来在需要同步的场景,因为内存都是在一台机器上,可以很容易的实现对共享资源的锁定,但是多主机部署时,如果我们要锁定一个共享资源,显然这种方式无法满足我们的需求了,因为多主机部署时,我们每个主机要读取共享资源,可能会存在先后的顺序,那么在同时操纵一个数据时,就可能会存在一些很严重的问题了。

二、举个栗子

  场景:2个用户同时对一个商品进行下单,商品库存只剩下1个,服务端会进行库存扣减。

  期望结果:1个用户能下单成功,另一个用户提示库存不足

  可能存在的问题:主机1和主机2同时去读取一个商品的库存,都发现是1,然后都进行了库存扣减,扣减完成后主机1进行了提交,库存被修改为0,这个时候主机2再进行提交,库存再次减1变为-1,那不就凉凉了么?

  解决方案:数据库锁,分布式锁等(这篇文章只讨论数据库层面做的锁,分布式锁可以戳这里~

三、代码实现

  场景:商品库存为0 ,而此时进来了一个用户的购买线程

方式一 :update语句的原子性(行锁特性)实现乐观锁

  乐观锁:乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测

-- 3、对商品id为1的商品进行库存扣减
UPDATE T_GDS_INFO
SET GDS_STOCK = GDS_STOCK - 1
WHERE
GDS_ID = 1
AND GDS_ID IN (
-- 2、这里要再封装一个结果集给外层的update语句进行条件过滤,否则一条语句直接操作同一张表,即进行select又进行update会报错
SELECT
A.GDS_ID
FROM
(
-- 1、查询库存大于等于1的商品(带入需要扣减库存的商品id)
SELECT
GDS_ID
FROM
T_GDS_INFO
WHERE
GDS_ID = 1
AND GDS_STOCK >= 1
) A
);

    上面的sql可能看着这比较绕,我们来一波简易的版本:

-- 1、当库存大于等于1时才进行库存扣减
UPDATE T_GDS_INFO
SET GDS_STOCK = GDS_STOCK - 1
WHERE
GDS_ID = 1
AND GDS_STOCK >= 1

方式二 :利用版本号实现乐观锁

  思路:表里增加一个版本号的字段进行控制,每次成功更新版本号增加1,当需要进行更新操作时,先查询出版本号,然后再把查询出来的版本号作为update语句的条件带入,此时如果多个线程请求同一条数据时,查询到的版本号虽然一致,但是只有第一个提交的线程能更新成功。

-- 1、查询商品信息 得到版本号
SELECT * FROM T_GDS_INFO;
-- 2、在语句里带入查询到的版本号,每次成功更新版本号+1
UPDATE T_GDS_INFO
SET GDS_STOCK = GDS_STOCK - 1,
VERSION = VERSION + 1
WHERE
GDS_ID = 1
AND VERSION = 1
-- 3、如果同时2个订购都读取到版本号是1,然后进行库存扣减,那么第一条UPDATE语句会成功,把版本号增加变成2,而第二条UPDATE语句带入条件的版本号还是1,则会更新失败

  PS:类似的还有用时间戳字段来进行版本控制的,思路类似,这里就不进行详细说明了

最新文章

  1. C#操作XML的方法
  2. one recursive approach for 3, hdu 1016 (with an improved version) , permutations, N-Queens puzzle 分类: hdoj 2015-07-19 16:49 86人阅读 评论(0) 收藏
  3. JTree使用
  4. xml ---DOM操作
  5. eclipse的maven项目报Missing artifact jdk.toos:jdk.toos:jar:1.6错
  6. *[codility]Peaks
  7. POJ 3422 Kaka's Matrix Travels(费用流)
  8. 实体类转Json的2种方法
  9. 判断括号字符串是否为合法+求n对括号的所有组合
  10. bzoj 2095: [Poi2010]Bridges [混合图欧拉回路]
  11. Unity进阶----AssetBundle_02(加载依赖关系及网络资源)(2018/10/31)
  12. Java包装类介绍与类型之间相互转换
  13. 2018-6-20-随笔-SQL Server中乱码
  14. EBS 请求输出Html报表集成Echarts
  15. Python CNN卷积神经网络代码实现
  16. Django登陆以后重定向到请求登陆的页面
  17. MySQL——索引实现原理
  18. table中background背景图片自动拉伸
  19. phpcms与discuz的ucenter整合
  20. 撩课-Web大前端每天5道面试题-Day6

热门文章

  1. 牛客网PAT练兵场-数字黑洞
  2. 区块链入门到实战(38)之Solidity – 条件语句
  3. 专为seo新手准备的百度分享工具教程
  4. OpenCV实现人脸检测
  5. UnitTest框架的快速构建与运行
  6. Mybatis通用Join的实现(最终版)
  7. 初学WebGL引擎-BabylonJS:第1篇-基础构造
  8. python小白入门基础(二:变量)
  9. 伪距定位算法(matlab版)
  10. OpenResty 作者章亦春访谈实录