Curator可重入分布式锁的实现

Curator实现zk分布式锁的确很简单,比zkclient便捷太多了。
部分内容参考 stwen 阿甘正专,向原作者致谢。

环境:SpringBoot,redis集群,zookeeper3.4.14,Curator4.2,jmeter测试。
相关依赖:
		<dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>zookeeper</artifactId>
                    <groupId>org.apache.zookeeper</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.7</version>
        </dependency>
        <!--  lombok包  @Data   :注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
                        同时可以使用@Slf4j注解-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
        <!--  springboot的配置文件解析依赖,可以通过注释@ConfigurationProperties生成元数据文件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.1.7.RELEASE</version>
        </dependency>
配置文件 application.properties
#重试次数
curator.retryCount=5
#重试间隔时间
curator.elapsedTimeMs=5000
#zookeeper 地址
curator.connectString=192.168.37.134:2181
#session超时时间
curator.sessionTimeoutMs=60000
#连接超时时间
curator.connectionTimeoutMs=5000

spring.redis.cluster.nodes=192.168.37.134:7001,192.168.37.134:7002,192.168.37.134:7003,192.168.37.134:7004,192.168.37.134:7005,192.168.37.134:7006
Configuration配置类
import lombok.Data;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
  
@Configuration
@ConfigurationProperties(prefix = "curator")
@Data
public class CuratorConfig {
   private int retryCount;                //连接重试次数
   private int elapsedTimeMs;             //重试的间隔时间
   private String connectString;          //zookeeper连接地址
   private int sessionTimeoutMs;          //session超时时间
   private int connectionTimeoutMs;       //连接超时时间

   @Bean(initMethod = "start")
   public CuratorFramework getCuratorFramework(){
      RetryPolicy retryPolicy=new ExponentialBackoffRetry(elapsedTimeMs,retryCount);
      CuratorFramework curatorFramework= CuratorFrameworkFactory.builder()
              .connectString(connectString)
              .sessionTimeoutMs(sessionTimeoutMs)
              .retryPolicy(retryPolicy)
              .build();
      return curatorFramework;

   }
}
测试业务类 ,实现分布式锁

取得可重入互斥锁InterProcessMutex,以lock.acquire()加锁,lock.release()解锁。

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
@Service
public class OrderImp {
    @Autowired
    private CuratorFramework curatorFramework;
    @Autowired
    private RedisTemplate<String,String> rt;
    private static int sellnum=0;                       //售出数量
    private final String path="/distribute/lock";       //zk临时节点位置
    /*redis现有库存 store=100*/
    public void generateOrder()
    {
        InterProcessMutex rlock=new InterProcessMutex(curatorFramework,path);

        try {
        rlock.acquire();
        log.info(Thread.currentThread().getName()+"取锁成功");
        int store=Integer.valueOf(rt.opsForValue().get("store"));
        if(0<store--){
            rt.opsForValue().set("store",String.valueOf(store));
            String ordernum=this.orderNumber("miphone");
            rt.opsForList().leftPush("order",ordernum);
            //System.out.printf("售出%d个,订单号为:%s\n",sellnum,ordernum);
            log.info("售出{}个,订单号为:{}",sellnum,ordernum);
        }else
            log.info("已售完,下次早些来吧");

    } catch (Exception e) {
        log.error("some wrong");
        e.printStackTrace();
    } finally {
        try {
            rlock.release();
            log.info(Thread.currentThread().getName()+"解锁");
        } catch (Exception e) {
            e.printStackTrace();
        }
        }
    }
    
//    生成订单编号,设编号格式为productID/MM-dd-HH:mm:ss,sellnum
    public String orderNumber(String productID){
        //当前时间
        SimpleDateFormat sdate=new SimpleDateFormat("MM-dd-HH:mm:ss");
        String datestring=sdate.format(new Date());
        return productID+"/"+datestring+(++sellnum);
    }
}
测试Controller

在这里插入图片描述

jmeter测试

500线程,重复2次访问。
在这里插入图片描述
在这里插入图片描述

结果正常

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值