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实现分布式事务的三种方案
Jun 11 Java/Android
Java elasticsearch安装以及部署教程
Jun 28 Java/Android
Java基础之线程锁相关知识总结
Jun 30 Java/Android
gateway网关接口请求的校验方式
Jul 15 Java/Android
Java Spring 控制反转(IOC)容器详解
Oct 05 Java/Android
Spring this调用当前类方法无法拦截的示例代码
Mar 20 Java/Android
SpringBoot2零基础到精通之数据与页面响应
Mar 22 Java/Android
Flutter集成高德地图并添加自定义Maker的实践
Apr 07 Java/Android
JAVA长虹键法之建造者Builder模式实现
Apr 10 Java/Android
Java工作中实用的代码优化技巧分享
Apr 21 Java/Android
Jmerte 分布式压测及分布式压测配置
Apr 30 Java/Android
springboot为异步任务规划自定义线程池的实现
Jun 14 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
Drupal读取Excel并导入数据库实例
2014/03/02 PHP
php设置允许大文件上传示例代码
2014/03/10 PHP
PHP大转盘中奖概率算法实例
2014/10/21 PHP
详解PHP的Yii框架中日志的相关配置及使用
2015/12/08 PHP
php中preg_replace_callback函数简单用法示例
2016/07/21 PHP
php中this关键字用法分析
2016/12/07 PHP
php pdo操作数据库示例
2017/03/10 PHP
JSON 入门指南 想了解json的朋友可以看下
2009/08/26 Javascript
一步一步教你写一个jQuery的插件教程(Plugin)
2009/09/03 Javascript
JQUBAR1.1 jQuery 柱状图插件发布
2010/11/28 Javascript
JavaScript高级程序设计(第3版)学习笔记4 js运算符和操作符
2012/10/11 Javascript
js事件(Event)知识整理
2012/10/11 Javascript
JS的location.href跳出框架打开新页面的方法
2014/09/04 Javascript
javascript实现动态模态绑定grid过程代码
2014/09/22 Javascript
jQuery调取jSon数据并展示的方法
2015/01/29 Javascript
详解Webwork中Action 调用的方法
2016/02/02 Javascript
JavaScript数据类型转换的注意事项
2016/07/31 Javascript
BootstrapValidator实现注册校验和登录错误提示效果
2017/03/10 Javascript
vue.js移动数组位置,同时更新视图的方法
2018/03/08 Javascript
ES6中Set和Map数据结构,Map与其它数据结构互相转换操作实例详解
2019/02/28 Javascript
Javascript 类型转换、封闭函数及常见内置对象操作示例
2019/11/15 Javascript
Node Express用法详解【安装、使用、路由、中间件、模板引擎等】
2020/05/13 Javascript
微信小程序:报错(in promise) MiniProgramError
2020/10/30 Javascript
使用python对文件中的数值进行累加的实例
2018/11/28 Python
如何更优雅地写python代码
2019/07/02 Python
python 的 openpyxl模块 读取 Excel文件的方法
2019/09/09 Python
python BlockingScheduler定时任务及其他方式的实现
2019/09/19 Python
如何使用python进行pdf文件分割
2019/11/11 Python
Python通过VGG16模型实现图像风格转换操作详解
2020/01/16 Python
python 中的命名空间,你真的了解吗?
2020/08/19 Python
python Protobuf定义消息类型知识点讲解
2021/03/02 Python
理工大学毕业生自荐信
2013/11/01 职场文书
《雷雨》教学反思
2014/02/20 职场文书
群众路线批评与自我批评发言稿
2014/10/16 职场文书
单位介绍信格式范文
2015/05/04 职场文书
Mysql MVCC机制原理详解
2021/04/20 MySQL