springboot+zookeeper实现分布式锁的示例代码
作者:冬雪是你 发布时间:2022-02-05 08:48:48
标签: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)),所以运行时间符合。
zookeeper每个线程在/rooLock节点下创建的临时有序节点如下图,由于是临时的,所以线程释放锁后这些节点也会删除
100个线程程序日志打印
关于InterProcessMutex内部如何实现zookeeper分布式锁,请看我写的这篇文章:在这里
来源:https://blog.csdn.net/m0_45097637/article/details/123591560


猜你喜欢
- RequestHeaders添加自定义参数在开发过程中有的时候,参数需要绑定到requestHeaders中,而并不是在body中进行传输。
- 程序入口:Test_Email_N.javaimport java.io.IOException;import java.util.Date
- 一、项目整体介绍:项目整体的结构如下图所示,项目整体采用 springboot + mybatis + jsp + mysql 来完成的,下
- 本文实例为大家分享了Android GestureDetector实现手势滑动的具体代码,供大家参考,具体内容如下目标效果: 程
- 最近在开发的过程当中,对于已有的代码,想将相关类绘制成UML类图,虽然现在有很多UML类图的优秀软件,比如ProcessOn(可视化编辑)、
- Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- 前言下面大部分内容来源于网上的相关帖子和官网,自己简单写了个demo体验了下,个人感觉mybatis的缓存并不是很合适查询做缓存时,遇到更新
- 本文介绍了Android TextView属性ellipsize多行失效的解决思路,分享给大家,具体如下:多余文字显示省略号的常规做法and
- Eclipse 最佳字体 推荐:步骤:Eclipse->Windows[窗口]->Preferences[首选项]->Ge
- 目录功能使用类 SuperAdapter 的作用类 AbsViewHolder 的作用Sample这个适配器我珍藏已久(近两年), 不断看到
- @RequestBody不能class类型匹配在首次第一次尝试使用@RequestBody注解开始加载字符串使用post提交(貌似只能pos
- 前言1、每一种要缓存的数据都是有对应的versionCode,通过versionCode请求网络获取是否需要更新 2、提前将要缓存的数据放入
- 目录一:背景二:从 dump 文件中提取源代码1. 案例演示2. 使用 lm + savemodule 命令提取3. 使用 dumpdoma
- 1 修饰类和方法package site.exciter.springmvc.handlers;import org.springframe
- 没有接触过音乐字幕方面知识的话,会对字幕的实现比较迷茫,什么时候转到下一句?看了这篇文章,你就会明白字幕so easy。先来一张效果图:字幕
- 本文实例为大家分享了java实现webservice方式的具体代码,供大家参考,具体内容如下经过测试 jdk1.6.10以下会出现bug 建
- 开发Android应用中,随着功能越来越多,启动速度越来越慢。有没有办法让自己应用启动速度快一点呢?方法是人想出来的。先说说我的实现方法:1
- 1、修改全局配置文件(application.yml)server: port: 9001 servlet: &nb
- 在Android开发中我们很多地方都用到了方法的回调,回调就是把方法的定义和功能导入实现分开的一种机制,目的是为了解耦他的本质是基于观察者设