分布式锁场景

350 阅读2分钟

      最近项目中有这样一个场景:商家在注册服务号的时候,要填写合同编号、上传合同文件、资质文件。其中要求不同的商家不能使用同一个合同编号,同一个商家可以共用一个合同编号。如果不考虑并发问题实现是这样的1、判断合同编号是否存在2、判断商家是否是同一个

2个逻辑用一条sql实现
select count(*) from table where contract_num ='xxx' and merchant_id <>'xxx';
java:代码
boolean flag = queryContractNumIsExist("contract_num ","merchant_id ");
if (flag) {    
    saveService();
}      

     但是如果并发量很大的情况下,同时好几个线程拿到flag的值都是true,那么这个时候就会造成不同的商家使用同一个合同编号。这个容易解决只要给这段代码上一把锁就行了,你可以使用synchronzed或者Lock

synchronzed(this){
    boolean flag = queryContractNumIsExsisOrNot("contract_num ","merchant_id ");
    if (flag) {    
        saveService();
    }
}

      但是现在基本上都是集群环境。集群环境中,如果一个请求线程A商家A执行是集群的A机器处理,线程B商家B执行是集群的B机器处理,线程A在A机器上判断flag是true。线程B在B机器上刚好保存了一条记录。那么这样也会造成不同的商家使用同一个合同编号。

      类似这样的场景还有很多,比多大家经常听说的超卖,下单,扣减库存,比如现在正好就剩一件商品,2个人同时去下单,A用户下单成功,库存还没来得及时扣减,这时候B用户也下单成功了,其实只有一件商品。根本原因就是下单和扣减库存是2个操作,集群环境下,这2个操作可能分别发生在不用服务器上,每个服务器都判断当前有剩余库存,都去执行下单操作了,

    这样的场景当然是使用的分布式锁,或者叫全局锁来来解决,后面我们来探讨一下使用redis实现分布式锁