• Oracle学习(十七)数据库锁在分布式系统里的应用(老板,乐观锁了解一下?~)


    一、引言

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

      那么我们知道如果是一台主机部署的话,我们有很多方式可以实现锁的概念,比如利用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:类似的还有用时间戳字段来进行版本控制的,思路类似,这里就不进行详细说明了

     

  • 相关阅读:
    全面分析 Spring 的编程式事务管理及声明式事务管理
    100句唤醒自己的励志名言
    100句自我激励的名言佳句
    java反射详解
    JAVA中的反射机制
    【BZOJ1015】【JSOI2008】星球大战Starwar(离线并差集)
    【HEOI2016/TJOI2016】排序(二份答案+线段树)
    【USACO06DEC】—牛奶模式Milk Patterns(后缀自动机)
    【HNOI2016】—找相同字符(后缀自动机)
    【AHOI2013】—差异(后缀自动机)
  • 原文地址:https://www.cnblogs.com/riches/p/12552414.html
Copyright © 2020-2023  润新知