当前位置: 首页 > article >正文

Zookeeper(58)如何在Zookeeper中实现分布式锁?

在 Zookeeper 中实现分布式锁是一种常见的用例。Zookeeper 提供了强一致性、高可用性的分布式协调服务,使得它非常适合用来实现分布式锁。以下是详细的步骤和代码示例,展示如何在 Zookeeper 中实现分布式锁。

1. Zookeeper 分布式锁的基本原理

Zookeeper 分布式锁的实现主要依赖于以下几点:

  1. 临时顺序节点:每个客户端在尝试获取锁时,会在特定节点下创建一个临时顺序节点。
  2. 节点排序:所有客户端创建的节点会按顺序排列,最小的节点获得锁。
  3. 监视前一个节点:每个客户端监视它前一个节点的变化,当前一个节点被删除时,当前客户端重新检查自己是否是最小的节点,如果是,则获得锁。

2. 添加依赖

首先,需要在项目中添加 Zookeeper 的依赖。以下是 Maven 和 Gradle 的依赖配置:

Maven

pom.xml 中添加 Zookeeper 依赖:

<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.7.0</version>
</dependency>
Gradle

build.gradle 中添加 Zookeeper 依赖:

dependencies {implementation 'org.apache.zookeeper:zookeeper:3.7.0'
}

3. 实现分布式锁

以下是一个完整的实现分布式锁的示例代码。

ZookeeperClient.java
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;public class ZookeeperClient {private static final String ZK_ADDRESS = "localhost:2181";private static final int SESSION_TIMEOUT = 3000;private ZooKeeper zooKeeper;public void connect() throws Exception {zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {@Overridepublic void process(WatchedEvent event) {System.out.println("Received event: " + event);}});}public void close() throws InterruptedException {if (zooKeeper != null) {zooKeeper.close();}}public ZooKeeper getZooKeeper() {return zooKeeper;}public static void main(String[] args) {ZookeeperClient client = new ZookeeperClient();try {client.connect();// 在这里可以测试分布式锁client.close();} catch (Exception e) {e.printStackTrace();}}
}
DistributedLock.java
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;import java.util.Collections;
import java.util.List;public class DistributedLock {private static final String LOCK_ROOT = "/locks";private static final String LOCK_NODE = LOCK_ROOT + "/lock_";private ZooKeeper zooKeeper;private String lockPath;public DistributedLock(ZooKeeper zooKeeper) throws Exception {this.zooKeeper = zooKeeper;Stat stat = zooKeeper.exists(LOCK_ROOT, false);if (stat == null) {zooKeeper.create(LOCK_ROOT, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);}}public void acquireLock() throws Exception {lockPath = zooKeeper.create(LOCK_NODE, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);System.out.println("Lock path: " + lockPath);while (true) {List<String> children = zooKeeper.getChildren(LOCK_ROOT, false);Collections.sort(children);String smallestChild = LOCK_ROOT + "/" + children.get(0);if (lockPath.equals(smallestChild)) {System.out.println("Acquired lock: " + lockPath);return;}String watchNode = null;for (int i = children.size() - 1; i >= 0; i--) {String child = LOCK_ROOT + "/" + children.get(i);if (child.compareTo(lockPath) < 0) {watchNode = child;break;}}if (watchNode != null) {final Object lock = new Object();Watcher watcher = new Watcher() {@Overridepublic void process(WatchedEvent event) {synchronized (lock) {lock.notifyAll();}}};Stat stat = zooKeeper.exists(watchNode, watcher);if (stat != null) {synchronized (lock) {lock.wait();}}}}}public void releaseLock() throws Exception {if (lockPath != null) {zooKeeper.delete(lockPath, -1);System.out.println("Released lock: " + lockPath);lockPath = null;}}public static void main(String[] args) {ZookeeperClient client = new ZookeeperClient();try {client.connect();ZooKeeper zooKeeper = client.getZooKeeper();DistributedLock lock = new DistributedLock(zooKeeper);lock.acquireLock();// 模拟业务逻辑Thread.sleep(5000);lock.releaseLock();client.close();} catch (Exception e) {e.printStackTrace();}}
}

4. 代码说明

ZookeeperClient 类

ZookeeperClient 类负责连接和关闭 Zookeeper 客户端,并提供获取 ZooKeeper 实例的方法。

DistributedLock 类

DistributedLock 类负责实现分布式锁的逻辑,包括获取锁和释放锁。

  • acquireLock() 方法:尝试获取锁,创建临时顺序节点,然后检查自己是否是最小的节点。如果是,则获得锁;否则,监视前一个节点的变化。
  • releaseLock() 方法:释放锁,删除自己创建的临时顺序节点。

5. 测试分布式锁

DistributedLock 类的 main 方法中,创建 ZookeeperClient 实例并连接 Zookeeper,然后创建 DistributedLock 实例并尝试获取和释放锁。可以通过运行多个实例来测试分布式锁的功能。

public static void main(String[] args) {ZookeeperClient client = new ZookeeperClient();try {client.connect();ZooKeeper zooKeeper = client.getZooKeeper();DistributedLock lock = new DistributedLock(zooKeeper);lock.acquireLock();// 模拟业务逻辑Thread.sleep(5000);lock.releaseLock();client.close();} catch (Exception e) {e.printStackTrace();}
}

总结

  1. 添加依赖:在项目中添加 Zookeeper 的依赖。
  2. 实现 ZookeeperClient 类:负责连接和关闭 Zookeeper 客户端,并提供获取 ZooKeeper 实例的方法。
  3. 实现 DistributedLock 类:负责实现分布式锁的逻辑,包括获取锁和释放锁。
  4. 测试分布式锁:通过运行多个实例来测试分布式锁的功能。

通过以上方法,可以在 Zookeeper 中实现分布式锁,确保其高效稳定地运行。根据实际情况和需求,选择适合你的实现方法并进行实施。

相关文章:

Zookeeper(58)如何在Zookeeper中实现分布式锁?

在 Zookeeper 中实现分布式锁是一种常见的用例。Zookeeper 提供了强一致性、高可用性的分布式协调服务&#xff0c;使得它非常适合用来实现分布式锁。以下是详细的步骤和代码示例&#xff0c;展示如何在 Zookeeper 中实现分布式锁。 1. Zookeeper 分布式锁的基本原理 Zookeep…...

23种设计模式 - 观察者模式

模式定义 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;定义了一对多的依赖关系&#xff1a;当一个对象&#xff08;称为主题&#xff09;状态变化时&#xff0c;所有依赖它的对象&#xff08;称为观察者&#xff09;会自动收到通知并…...

conda、anaconda、pip、pytorch、tensorflow有什么区别?

先画一张图&#xff0c;可以大致看出它们的区别和关联&#xff1a; pytorch、tensorflow都是Python的第三方库&#xff0c;相当于封装的代码工具集库&#xff0c;通过import导入使用。这两个都是深度学习框架&#xff0c;用来搭建AI模型什么的&#xff0c;使用范围非常之广&…...

项目设置内网 IP 访问实现方案

在我们平常的开发工作中&#xff0c;项目开发、测试完成后进行部署上线。比如电商网站、新闻网站、社交网站等&#xff0c;通常对访问不会进行限制。但是像企业内部网站、内部管理系统等&#xff0c;这种系统一般都需要限制访问&#xff0c;比如内网才能访问等。那么一个网站应…...

Vue面试2

1.跨域问题以及如何解决跨域 跨域问题&#xff08;Cross-Origin Resource Sharing, CORS&#xff09;是指在浏览器中&#xff0c;当一个资源试图从一个不同的源请求另一个资源时所遇到的限制。这种限制是浏览器为了保护用户安全而实施的一种同源策略&#xff08;Same-origin p…...

合合信息2025届春季校园招聘全面启动!

世界因你而AI&#xff0c;合合信息2025届春季校园招聘启动&#xff01; 我们是谁&#xff1f; 我们是一家行业领先的人工智能及大数据科技企业 18年深耕AI领域&#xff0c;C端产品与B端服务布局矩阵完善 9.4亿全球累计用户首次下载量&#x1f4a5; 来到这里你能得到什么&a…...

如何利用 Vue 的生命周期钩子进行初始化和清理操作?

一、初始化操作的核心钩子 1. created&#xff08;选项式API&#xff09; export default {data() {return { user: null };},created() {// 适合初始化数据、发起非DOM操作请求this.fetchUser();},methods: {async fetchUser() {const response await fetch(/api/user);thi…...

Excell 代码处理

文章目录 Excell 代码处理cvc格式xlsl格式小结 Excell 代码处理 有时候要对excell进行分析&#xff0c;或者数据的导入导出&#xff0c;这个时候如果可以用代码读写分析操作那么会方便很多 cvc格式 CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff09;是…...

KMP的next数组构建详解

KMP的next数组构建详解 1. next数组的作用 核心功能&#xff1a;在KMP算法中&#xff0c;当模式串与主串发生不匹配时&#xff0c;next数组决定模式串指针回退的位置&#xff0c;避免无效匹配。 定义&#xff1a;next[i]表示子串s[0...i]的最长公共前后缀长度。例如&#xff…...

Docker 的安全配置与优化(二)

Docker 安全优化策略 &#xff08;一&#xff09;多阶段构建优化镜像大小 多阶段构建是 Docker 17.05 版本引入的强大功能&#xff0c;它允许在一个 Dockerfile 中定义多个构建阶段&#xff0c;每个阶段都可以使用不同的基础镜像和依赖项&#xff0c;最终只将必要的文件和依赖…...

shiro代码层面追踪

文章目录 环境漏洞分析硬编码 反序列化Gadget构造 环境 环境搭建&#xff1a;https://blog.csdn.net/qq_44769520/article/details/123476443 漏洞分析 硬编码 shiro是对rememberMe这个cookie进⾏反序列化的时候出现了问题。 相应代码 // // Source code recreated from …...

通信系统中物理层与网络层联系与区别

在通信系统中&#xff0c;物理层和网络层是OSI&#xff08;开放系统互连&#xff09;模型中的两个重要层次&#xff0c;分别位于协议栈的最底层和第三层。它们在功能、职责和实现方式上有显著的区别&#xff0c;但同时也在某些方面存在联系。以下是物理层与网络层的联系与区别的…...

虚拟机网络ssh连接失败,没有网络

vscode进行ssh时连接失败&#xff0c;发现是虚拟机没有网络。 虚拟机ping不通www.baidu.com但可以ping通内网 ping 8.8.8.8ping不通。 sudo dhclient -r ens33 sudo dhclient ens33 ip route show可以了。 20250221记录&#xff1a;不知道是不是重启了虚拟机还是咋了&#…...

已知点矩阵的三个顶点坐标、行列数和行列的间距,计算得出剩余所有点的坐标

已知点矩阵的三个顶点坐标、行列数和行列的间距&#xff0c;计算得出剩余所有点的坐标 计算矩阵中每个点的坐标代码实现案例图调用验证 计算矩阵中每个点的坐标 给定左上角、左下角和右上角三个点的坐标&#xff0c;以及矩阵的行数、列数、行间距和列间距&#xff0c;我们可以…...

Python Cookbook-2.4 从文件中读取指定的行

任务 根据给出的行号&#xff0c;从文本文件中读取一行数据。 解决方案 Python标准库linecache模块非常适合这个任务: import linecache theline linecache.getline(thefilepath, desired_line_number)讨论 对这个任务而言&#xff0c;标准的 linecache 模块是 Python 能…...

go 并发 gorouting chan channel select Mutex sync.One

goroutine // head&#xff1a; 前缀 index&#xff1a;是一个int的指针 func print(head string, index *int) {for i : 0; i < 5; i {// 指针对应的int *indexfmt.Println(*index, head, i)// 暂停1stime.Sleep(1 * time.Second)} }/* Go 允许使用 go 语句开启一个新的运…...

Unity游戏制作中的C#基础(3)加减乘除算术操作符,比较运算符,逻辑与,或运算符

1. 基本算术运算符 算术运算符主要用于对数值类型&#xff08;整型和浮点型&#xff09;进行基本的数学运算。以下是常见的算术运算符及其说明&#xff1a; 运算符描述示例结果加法运算符&#xff0c;用于两个数相加&#xff0c;也可用于字符串连接int a 5 3; string str &…...

深度学习入门--python入门2

以前学的全忘了&#xff0c;现在算是才开始学&#xff0c;有错误&#xff0c;恳请指正。 目录 1.4 Python脚本文件 1.4.1保存为文件 1.4.2 类 1.5 Numpy 1.5.1 导入Numpy 1.5.2 生成Numpy数组 1.5.3 Numpy的算术运算 1.5.4 Numpy的N维数组 1.5.5 广播 1.5.6 访问元素…...

题海拾贝:【枚举】P2010 [NOIP 2016 普及组] 回文日期

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞&#xff0c;关注&#xff01; 1、题…...

Mac端homebrew安装配置

拷打了一下午o3-mini-high&#xff0c;不如这位博主的超强帖子&#xff0c;10分钟结束战斗 跟随该文章即可&#xff0c;2025/2/19亲测可行 mac 安装HomeBrew(100%成功)_mac安装homebrew-CSDN博客文章浏览阅读10w次&#xff0c;点赞258次&#xff0c;收藏837次。一直觉得自己写…...

Web - JS基础语法与表达式

概述 这篇文章主要介绍了 JavaScript 的基础语法&#xff0c;包括代码书写位置、ERPL 环境、变量&#xff08;命名规则、默认值、初始化&#xff09;、数据类型&#xff08;基本和复杂&#xff0c;及各类型特点、转换&#xff09;、表达式和运算符&#xff08;算数、特殊算数、…...

Python高级语法之selenium

目录&#xff1a; 1、selenium的使用2、selenium元素定位3、selenium使用功能Phantomjs模拟浏览器启动4、selenium使用功能ChromsHandless模拟浏览器启动 1、selenium的使用 2、selenium元素定位 3、selenium使用功能Phantomjs模拟浏览器启动 4、selenium使用功能ChromsHandles…...

AIP-148 标准域

编号148原文链接AIP-148: Standard fields状态批准创建日期2020-10-06更新日期2020-10-06 一些概念在任何API集合中都很常用。对于这些概念&#xff0c;使用统一的标准域名字和行为来表达它们&#xff0c;是非常有用的。 指南 标准域 应当 用于描述其相应概念&#xff0c; 不…...

Docker构建时,设定默认进入的工作目录的方法

在 Docker 中,你可以通过不同的方式来设定容器默认进入的目录,以下针对不同场景分别介绍具体方法: 1. 使用 Dockerfile 设定工作目录 如果你是通过构建镜像的方式来运行容器,那么可以在 Dockerfile 中使用 WORKDIR 指令来设置容器启动时的默认工作目录。以下是具体步骤:…...

2025年3月最新算法-鲸鱼迁徙优化算法Whale Migration Algorithm-附Matlab免费代码

引言 本期介绍了一种基于座头鲸协同迁移行为的创新生物启发式优化方法——鲸鱼迁徙优化算法Whale Migration Algorithm&#xff0c;WMA。该算法于2025年3月最新发表在期刊 Results in Engineering 在本节中&#xff0c;我们概述了开发鲸鱼迁移算法&#xff08;WMA&#xff09;…...

day56 第十一章:图论part06

108.冗余连接 注意init初始化 改进&#xff1a; 其实只有一条边冗余&#xff0c;改为&#xff0c;如果两条边在同一个集合里&#xff0c;就输出&#xff0c;不然加入。 #include <iostream> #include <vector> using namespace std;int n 1005; vector<int>…...

flowable适配达梦数据库

文章目录 适配相关问题无法从数据库产品名称“DM DBMS”中推断数据库类型分析解决 构建ibatis SqlSessionFactory时出错&#xff1a;inStream参数为null分析解决 liquibase相关问题问题一&#xff1a;不支持的数据库 Error executing SQL call current_schema: 无法解析的成员访…...

Jenkins整合Jmeter实现接口自动化测试

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、安装jmeter 下载&#xff1a;http://jmeter.apache.org/download_jmeter.cgi 这里我用了一台Windows安装jmeter用来写接口测试的脚本&#xff0c;启动前修改j…...

高级推理的多样化推理与验证

25年2月来自波士顿大学、NotBadMath.AI、谷歌、哥伦比亚大学、MIT、Intuit公司和斯坦福大学的论文“Diverse Inference and Verification for Advanced Reasoning”。 OpenAI o1、o3 和 DeepSeek R1 等推理 LLM 在数学和编码方面取得重大进展&#xff0c;但仍发现 IMO 组合问题…...

深入理解 MySQL 8 C++ 源码:SELECT MOD(MONTH(NOW()), 2) 的函数执行过程

MySQL 作为最流行的关系型数据库之一&#xff0c;其内部实现机制一直是开发者探索的热点。本文将以一条简单的 SQL 查询 SELECT MOD(MONTH(NOW()), 2) 为例&#xff0c;深入分析 MySQL 8 源码中内置函数 MOD、MONTH 和 NOW 的执行过程&#xff0c;揭示其底层实现逻辑。 一、SQL…...