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 相关文章推荐
ConstraintValidator类如何实现自定义注解校验前端传参
Jun 18 Java/Android
Spring boot应用启动后首次访问很慢的解决方案
Jun 23 Java/Android
Springboot集成阿里云OSS上传文件系统教程
Jun 28 Java/Android
新手初学Java List 接口
Jul 07 Java/Android
Java 使用类型为Object的变量指向任意类型的对象
Apr 13 Java/Android
java版 简单三子棋游戏
May 04 Java/Android
Spring中的@Transactional的工作原理
Jun 05 Java/Android
详解Spring Bean的配置方式与实例化
Jun 10 Java/Android
springboot集成redis存对象乱码的问题及解决
Jun 16 Java/Android
Spring Boot 的创建和运行示例代码详解
Jul 23 Java/Android
HttpClient实现表单提交上传文件
Aug 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
discuz 首页四格:最新话题+最新回复+热门话题+精华文章插件
2007/08/19 PHP
php的chr和ord函数实现字符加减乘除运算实现代码
2011/12/05 PHP
Nginx+php配置文件及原理解析
2020/12/09 PHP
封装好的省市地区联动控件附下载
2007/08/13 Javascript
15款优秀的jQuery导航菜单插件分享
2011/07/19 Javascript
JS 模态对话框和非模态对话框操作技巧汇总
2013/04/15 Javascript
jQuery .tmpl() 用法示例介绍
2014/08/21 Javascript
jQuery手机浏览器中拖拽动作的艰难性分析
2015/02/04 Javascript
轻松理解Javascript变量的相关问题
2017/01/20 Javascript
js css自定义分页效果
2017/02/24 Javascript
JS实现针对给定时间的倒计时功能示例
2017/04/11 Javascript
详解最新vue-cli 2.9.1的webpack存在问题
2017/12/16 Javascript
nodejs实现一个word文档解析器思路详解
2018/08/14 NodeJs
vuex页面刷新后数据丢失的方法
2019/01/17 Javascript
Vue.js实现备忘录功能
2019/06/26 Javascript
layui table单元格事件修改值的方法
2019/09/24 Javascript
用Angular实现一个扫雷的游戏示例
2020/05/15 Javascript
js利用iframe实现选项卡效果
2020/08/09 Javascript
Express 配置HTML页面访问的实现
2020/11/01 Javascript
[01:34]传奇从这开始 2016国际邀请赛中国区预选赛震撼开启
2016/06/26 DOTA
[44:37]完美世界DOTA2联赛PWL S3 Forest vs access 第一场 12.11
2020/12/13 DOTA
Python获取运行目录与当前脚本目录的方法
2015/06/01 Python
Python读写/追加excel文件Demo分享
2018/05/03 Python
python numpy 一维数组转变为多维数组的实例
2018/07/02 Python
Python Pandas数据中对时间的操作
2019/07/30 Python
tensorflow实现打印ckpt模型保存下的变量名称及变量值
2020/01/04 Python
Python实现队列的方法示例小结【数组,链表】
2020/02/22 Python
keras实现多GPU或指定GPU的使用介绍
2020/06/17 Python
pycharm中使用request和Pytest进行接口测试的方法
2020/07/31 Python
python实现简单的五子棋游戏
2020/09/01 Python
DERMAdoctor官网:美国著名皮肤护理品牌
2019/07/06 全球购物
日本最大的彩色隐形眼镜销售网站:CharmColor
2020/09/09 全球购物
学校督导评估方案
2014/06/10 职场文书
幸福中国演讲稿
2014/09/12 职场文书
大学学生会主席竞选稿怎么写?
2019/08/19 职场文书
基于Redis实现分布式锁的方法(lua脚本版)
2021/05/12 Redis