springboot+zookeeper实现分布式锁


Posted in Java/Android onMarch 21, 2022

springboot+zookeeper实现分布式锁

InterProcessMutex内部实现了zookeeper分布式锁的机制,所以接下来我们尝试使用这个工具来为我们的业务加上分布式锁处理的功能

zookeeper分布式锁的特点:1、分布式 2、公平锁 3、可重入

依赖

<dependency>
   <groupId>org.apache.zookeeper</groupId>
   <artifactId>zookeeper</artifactId>
   <version>3.4.10</version>
</dependency>
<!-- zookeeper 客户端 -->
<dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-framework</artifactId>
   <version>2.12.0</version>
</dependency>
<dependency>
   <groupId>org.apache.curator</groupId>
   <artifactId>curator-recipes</artifactId>
   <version>2.12.0</version>
</dependency>
<!-- lombok -->
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <version>1.18.16</version>
   <scope>provided</scope>
</dependency>

本地封装

这个工具类主要封装CuratorFramework这个client(连接Zookeeper)

@Slf4j
public class CuratorClientUtil {
    private String zookeeperServer;

    @Getter
    private CuratorFramework client;

    public CuratorClientUtil(String zookeeperServer) {
        this.zookeeperServer = zookeeperServer;
    }

  	// 创建CuratorFrameworkFactory并且启动
    public void init() {
       // 重试策略,等待1s,最大重试3次
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
        this.client = CuratorFrameworkFactory.builder()
                .connectString(zookeeperServer)
                .sessionTimeoutMs(5000)
                .connectionTimeoutMs(5000)
                .retryPolicy(retryPolicy)
                .build();
        this.client.start();
    }

   // 容器关闭,CuratorFrameworkFactory关闭
    public void destroy() {
        try {
            if (Objects.nonNull(getClient())) {
                getClient().close();
            }
        } catch (Exception e) {
            log.info("CuratorFramework close error=>{}", e.getMessage());
        }
    }
}

配置

@Configuration
public class CuratorConfigration {
    @Value("${zookeeper.server}")
    private String zookeeperServer;
    // 注入时,指定initMethod和destroyMethod
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public CuratorClientUtil curatorClientUtil() {
        CuratorClientUtil clientUtil = new CuratorClientUtil(zookeeperServer);
        return clientUtil;
    }
}

测试代码

模拟不同客户端的请求

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
    // 注入client工具类
    @Autowired
    private CuratorClientUtil curatorClientUtil;
    // 在zookeeper的/rootLock节点下创建锁对应的临时有序节点
    private String rootLock = "/rootLock";

    @GetMapping("/testLock")
    public Object testLock() throws Exception {
        // 获取当前线程的名字,方便观察那些线程在获取锁
        String threadName = Thread.currentThread().getName();
        InterProcessMutex mutex = new InterProcessMutex(curatorClientUtil.getClient(), rootLock);
        try {
            log.info("{}---获取锁start", threadName);
            // 尝试获取锁,最长等待3s,超时放弃获取
            boolean lockFlag = mutex.acquire(3000, TimeUnit.SECONDS);
            // 获取锁成功,进行业务处理
            if (lockFlag) {
                log.info("{}---获取锁success", threadName);
                // 模拟业务处理,时间为3s
                Thread.sleep(3000);
            } else {
                log.info("{}---获取锁fail", threadName);
            }
        } catch (Exception e) {
            log.info("{}---获取锁异常", threadName);
        } finally {
            // 业务处理完成,释放锁,唤醒比当前线程创建的节点序号大(最靠近)的线程获取锁
            mutex.release();
            log.info("{}---锁release", threadName);
        }
        return "线程:" + threadName + "执行完成";
    }
}

JMeter测试

我们使用JMeter模拟100个客户端同时并发的访问 localhost:8081/test/testLock,相当于100个客户端争抢分布式锁,结果如图右上角所示,100个请求花了5分6s,每个线程获取到锁后业务处理3s,100个线程理想时间为300s(Thread.sleep(3000)),所以运行时间符合。
springboot+zookeeper实现分布式锁springboot+zookeeper实现分布式锁

zookeeper每个线程在/rooLock节点下创建的临时有序节点如下图,由于是临时的,所以线程释放锁后这些节点也会删除
springboot+zookeeper实现分布式锁
100个线程程序日志打印
springboot+zookeeper实现分布式锁

关于InterProcessMutex内部如何实现zookeeper分布式锁,请看我写的这篇文章:在这里

Java/Android 相关文章推荐
Java并发编程之Executor接口的使用
Jun 21 Java/Android
Java基于字符界面的简易收银台
Jun 26 Java/Android
解决SpringBoot跨域的三种方式
Jun 26 Java/Android
详解Java ES多节点任务的高效分发与收集实现
Jun 30 Java/Android
Java并发编程之原子性-Atomic的使用
Mar 16 Java/Android
spring cloud eureka 服务启动失败的原因分析及解决方法
Mar 17 Java/Android
Java GUI编程菜单组件实例详解
Apr 07 Java/Android
Java 垃圾回收超详细讲解记忆集和卡表
Apr 08 Java/Android
Java版 单机五子棋
May 04 Java/Android
spring IOC容器的Bean管理XML自动装配过程
May 30 Java/Android
Java实现添加条码或二维码到Word文档
Jun 01 Java/Android
Java Redisson多策略注解限流
Sep 23 Java/Android
Mybatis-Plus进阶分页与乐观锁插件及通用枚举和多数据源详解
Mar 21 #Java/Android
Spring this调用当前类方法无法拦截的示例代码
SpringCloud Feign请求头删除修改的操作代码
Mar 20 #Java/Android
JavaWeb实现显示mysql数据库数据
关于Mybatis中SQL节点的深入解析
springboot 自定义配置 解决Boolean属性不生效
Mar 18 #Java/Android
使用Java去实现超市会员管理系统
Mar 18 #Java/Android
You might like
php去除头尾空格的2种方法
2015/03/16 PHP
PHP性能优化大全(php.ini)
2016/05/20 PHP
PHP基于imagick扩展实现合成图片的两种方法【附imagick扩展下载】
2017/11/14 PHP
ThinkPHP框架实现的邮箱激活功能示例
2018/06/15 PHP
Ubuntu 11.10 安装Node.js的方法
2011/11/30 Javascript
Javascript 加载和执行-性能提高篇
2012/12/28 Javascript
js中事件的处理与浏览器对象示例介绍
2013/11/29 Javascript
基于JavaScript实现下拉列表左右移动代码
2017/02/07 Javascript
JavaScript hasOwnProperty() 函数实例详解
2017/08/04 Javascript
vue.js父子组件通信动态绑定的实例
2018/09/28 Javascript
浅谈js闭包理解
2019/04/01 Javascript
Vue中的组件及路由使用实例代码详解
2019/05/22 Javascript
详解vue-template-admin三级路由无法缓存的解决方案
2020/03/10 Javascript
[02:56]DOTA2英雄基础教程 巨魔战将
2013/12/10 DOTA
Python中用于转换字母为小写的lower()方法使用简介
2015/05/19 Python
python遍历目录的方法小结
2016/04/28 Python
python绘制地震散点图
2019/06/18 Python
nginx+uwsgi+django环境搭建的方法步骤
2019/11/25 Python
python实现单目标、多目标、多尺度、自定义特征的KCF跟踪算法(实例代码)
2020/01/08 Python
Python实现新型冠状病毒传播模型及预测代码实例
2020/02/05 Python
windows上彻底删除jupyter notebook的实现
2020/04/13 Python
Python新手如何理解循环加载模块
2020/05/29 Python
Python tkinter界面实现历史天气查询的示例代码
2020/08/23 Python
python 求两个向量的顺时针夹角操作
2021/03/04 Python
HTML5添加鼠标悬浮音响效果不使用FLASH
2014/04/23 HTML / CSS
html5 canvas移动浏览器上实现图片压缩上传
2016/03/11 HTML / CSS
企业治理工作自我评价
2013/09/26 职场文书
《三个小伙伴》教学反思
2014/04/11 职场文书
体育教师求职信
2014/05/24 职场文书
党委书记个人对照检查材料
2014/09/15 职场文书
2014年党建工作总结
2014/11/11 职场文书
教师节寄语2015
2015/03/23 职场文书
高中体育课教学反思
2016/02/16 职场文书
导游词之烟台威海蓬莱
2019/11/14 职场文书
Java实现经典游戏泡泡堂的示例代码
2022/04/04 Java/Android
Web应用开发TypeScript使用详解
2022/05/25 Javascript