刚接触分布式时就听说过分布式和单机的种种不同,于是今天就来准备来了解了解分布式锁。
在谈分布式锁之前先来看看不使用锁时会出现什么问题?
场景1: 假设现在有一个订单系统和一个库存系统,具体业务流程为:用户发起请求>>判断库存是否充足>>生成订单>>执行出库。
实现如下:
订单系统

@RestController
public class hello {
  public static int aaa=0;//统计生成的订单数
  @RequestMapping("/order_form")
  public String order_form() throws InterruptedException {
      aaa++;
      Thread.sleep(30);
      return "----------成功生成订单---累计生成订单数"+aaa;
  }
}

库存系统

//库存系统
@RestController
public class test {
   public static Integer repositoryNum=100;//初始库存
   public static Integer shellNum=0;//剩余库存数
   //检查库存是否充足
    @RequestMapping("/check_num")
    public boolean check_num(){
        return repositoryNum>=5;
    }
   //出库
   @RequestMapping("/reduce")
    public Integer reduce(int num){
          public Integer sell(int num) {
            try {
                Thread.sleep(50);//线程阻塞50毫秒模拟业务执行过程
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            test.repositoryNum-=num;
            test.shellNum+=num;
            System.out.println("成功卖出="+num+"共卖出"+test.shellNum+",剩余库存="+test.repositoryNum);
         return  test.repositoryNum;
    }
    }
 }

feign接口

@RestController
public class controller {
    @Autowired
    OrderFeign order;//订单系统
    @Autowired
    RepositoryFeign repository;//库存系统

    //销售业务
    @RequestMapping("/shell")
    public synchronized String shell() {
                if(repository.check()){
                    //产生订单
                    String result=order.order_form();
                    //开始出库
                    Integer num=repository.reduce(5);
                    return result+"剩余:"+num;
                }else{
                    System.out.println("剩余库存不足,出库失败");
                    return "剩余库存不足,出库失败";
                }
    }
}

Eureka:
为什么要使用分布式锁?
测试结果:
为什么要使用分布式锁?
通过9091端口和9090端口都可以实现销售的业务。这样看来似乎是没什么问题的。并且我们在feign的业务方法中加上了synchronized关键字,保证了多线程环境下的数据一致性。
于是我再次通过zuul网关进行访问,zuul网关会将请求依次发送到9090或9091端口进行执行。
为什么要使用分布式锁?
看起来依然没有毛病,可以正常的实现销售业务。于是我又通过jmeter模拟了100个用户并发访问。这时候问题出现了
为什么要使用分布式锁?
可以看到当库存为0时依然卖出了5件商品。这是因为当库存剩余5个时,9090端口先请求库存系统发现库存充足,9091端口又请求了库存系统发现库存充足。于是9090和9091端口都执行了出库操作。这样看来我们即使加上synchronized关键字后依然不能保证分布式中的数据一致性问题。

总结: 分布式环境中,服务通常是部署在多个服务器中,多台服务器无法使用同一把锁,所以引入了分布式锁这一概念。

感谢大佬文章:https://mp.weixin.qq.com/s/RLeujAj5rwZGNYMD0uLbrg

相关文章: