Spring cloud 中用curator框架实现分布式锁


前言

本文主要举例说明为什么要用分布式锁,以及介绍在Spring cloud 中用curator框架实现分布式锁。
学习项目地址


一、为什么要用分布式锁?

这个系统有 passager-api , order-service, pay-service 三个模块,其中 order-service 和 pay-service 是服务提供者,passager-api是消费者。(pay-service其实在这里没有用到,只要关注passager-api 和 order-service即可。)

order-service中有TblInventoryController
TblInventoryController 中的 decreaseStock 方法,会将商品表中表示库存数量的值减1,这个方法在扣减之前会取库存值判断是否大于0,如果小于等于0,则不会再扣减。

passager-api 中会调用这个方法,实现库存数量的正确扣减

如果passager-api只运行了一个实例,由于controller类默认都是单例模式,这个“扣减操作”顺序执行,不会有问题
如果passager-api运行了多个实例,order-service运行了多个实例,多个并发请求进行扣减,就可能出现库存被扣减到小于0的情况,也就是出现了异常。

加上分布式锁,可以使得一个时间点内只有一个扣减操作发生,避免扣减库存至负值的情况。

二、引入curator

<dependency>
	 <groupId>org.apache.curator</groupId>
     <artifactId>curator-recipes</artifactId>
     <version>5.6.0</version>
</dependency>

三、配置zookeeper

在启动类中,写了一个bean,连到本地的zookepper

@Bean
    public CuratorFramework curatorFramework() {
        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("localhost:2181", retryPolicy);
        curatorFramework.start();
        return curatorFramework;
    }

另:可以在docker中启动zookeeper

docker run -d --name zookeeper -p 2181:2181 zookeeper

四、代码中加上分布式锁

代码如下(示例):

		String lockStr = "/lock";
        InterProcessMutex lock = new InterProcessMutex(client, lockStr);
        try{
            if(lock.acquire(10, TimeUnit.HOURS)){
                System.out.println(userId +"获取锁成功");
                iOrderService.decreaseStock();   
            }else{
                System.out.println(userId +"未获取到锁");
            }
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            try{
                lock.release();
                System.out.println("释放资源");
            }catch (Exception e){
                e.printStackTrace();
            }
        }

说明

数据库使用的mysql,商品表 的建表语句在文件 tbl_inventory.sql 中。
程序运行后,要测试,访问的地址为:http://localhost:9001/webclient/test?userId=${id}

还可以再起一个实例,访问地址为:http://localhost:9000/webclient/test?userId=${id}
idea 另起一个实例,使用不同的端口号,是在 run/debug configuration 中, --server.port=****

然后用jmeter新建两个ThreadGroup并发访问,${id}从一个csv文件中读取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值