使用ZooKeeper实现分布式锁

news/发布时间2024/5/28 8:50:56

目录

引言

1. ZooKeeper简介

2. 分布式锁实现原理

3. 分布式锁实现步骤

步骤一:创建ZooKeeper客户端

步骤二:创建分布式锁类

步骤三:使用分布式锁

4. 总结


引言

在分布式系统中,实现分布式锁是一项常见的任务,可以用于保证同一时间只有一个客户端可以访问共享资源,从而避免竞争条件。ZooKeeper是一个开源的分布式协调服务,可以用来实现分布式锁。本文将介绍如何使用ZooKeeper实现分布式锁,并给出相应的代码示例。

1. ZooKeeper简介

ZooKeeper是一个高性能的分布式协调服务,提供了诸如配置管理、命名服务、分布式锁等功能。ZooKeeper通过维护一个具有层次结构的数据结构(类似于文件系统),来管理分布式应用程序的状态。

2. 分布式锁实现原理

在ZooKeeper中实现分布式锁的基本原理是利用ZooKeeper的顺序节点(Sequential Node)和临时节点(Ephemeral Node)特性。

  1. 客户端尝试在ZooKeeper中创建一个带有指定路径的临时顺序节点,例如/locks/lock-000000001
  2. 客户端获取/locks节点下的所有子节点,并按节点名称的顺序排序。
  3. 客户端判断自己创建的节点是否为最小节点,如果是,则认为获取锁成功;否则,监听自己前一个节点的删除事件,并进入等待状态。
  4. 当前最小节点的客户端完成操作后,删除自己创建的节点,触发监听的客户端继续判断是否为最小节点,直到获取锁成功。

3. 分布式锁实现步骤

步骤一:创建ZooKeeper客户端

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;import java.io.IOException;
import java.util.concurrent.CountDownLatch;public class ZooKeeperClient {private static final String CONNECT_STRING = "localhost:2181";private static final int SESSION_TIMEOUT = 5000;private static ZooKeeper zooKeeper;public static ZooKeeper getZooKeeper() throws IOException, InterruptedException {final CountDownLatch connectedSignal = new CountDownLatch(1);zooKeeper = new ZooKeeper(CONNECT_STRING, SESSION_TIMEOUT, new Watcher() {public void process(WatchedEvent event) {if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {connectedSignal.countDown();}}});connectedSignal.await();return zooKeeper;}public static void close() throws InterruptedException {if (zooKeeper != null) {zooKeeper.close();}}
}

步骤二:创建分布式锁类

import org.apache.zookeeper.*;import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;public class DistributedLock {private final ZooKeeper zooKeeper;private final String lockPath;private String currentLockPath;public DistributedLock(String lockPath) throws IOException, InterruptedException, KeeperException {this.zooKeeper = ZooKeeperClient.getZooKeeper();this.lockPath = lockPath;ensurePathExists(lockPath);}private void ensurePathExists(String path) throws KeeperException, InterruptedException {if (zooKeeper.exists(path, false) == null) {zooKeeper.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);}}public void lock() throws KeeperException, InterruptedException {currentLockPath = zooKeeper.create(lockPath + "/lock-", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);while (true) {List<String> children = zooKeeper.getChildren(lockPath, false);String minChild = getMinNode(children);if (currentLockPath.equals(lockPath + "/" + minChild)) {return;}waitForLock(minChild);}}private String getMinNode(List<String> children) {String minChild = children.get(0);for (String child : children) {if (child.compareTo(minChild) < 0) {minChild = child;}}return minChild;}private void waitForLock(String minChild) throws KeeperException, InterruptedException {final CountDownLatch latch = new CountDownLatch(1);Watcher watcher = new Watcher() {public void process(WatchedEvent event) {if (event.getType() == Event.EventType.NodeDeleted) {latch.countDown();}}};String prevNode = getPrevNode(minChild);zooKeeper.exists(lockPath + "/" + prevNode, watcher);latch.await();}private String getPrevNode(String minChild) throws KeeperException, InterruptedException {List<String> children = zooKeeper.getChildren(lockPath, false);String prevNode = null;for (String child : children) {if (child.equals(minChild)) {break;}prevNode = child;}return prevNode;}public void unlock() throws KeeperException, InterruptedException {zooKeeper.delete(currentLockPath, -1);currentLockPath = null;}
}

步骤三:使用分布式锁

public class Main {private static final String LOCK_PATH = "/locks";public static void main(String[] args) {try {DistributedLock lock = new DistributedLock(LOCK_PATH);lock.lock();// TODO: 处理业务逻辑lock.unlock();} catch (IOException | InterruptedException | KeeperException e) {e.printStackTrace();}}
}

4. 总结

本文介绍了使用ZooKeeper实现分布式锁的基本原理和步骤,并给出了相应的Java代码示例。在实际应用中,可以根据具体的需求和系统架构选择合适的分布式锁实现方式,从而保证系统的并发访问安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.bcls.cn/egwD/3775.shtml

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

IDEA-常用插件

1、Mybatis Log Free 当我们使用mybatis log在控制台输出sql 内容&#xff0c;输出内容将语句与参数分开打印&#xff0c;还需要手动将参数替换到指定位置。 使用对应插件后&#xff0c;自动将输出内容组装成完整的可直接执行的SQL 在插件市场 查看对应名称&#xff0c;并安装。…

alist修改密码(docker版)

rootarmbian:~# docker exec -it [docker名称] ./alist admin set abcd123456 INFO[2024-02-20 11:06:29] reading config file: data/config.json INFO[2024-02-20 11:06:29] load config from env with prefix: ALIST_ INFO[2024-02-20 11:06:29] init logrus..…

【Ubuntu】通过网线连接两台电脑以实现局域网连接的方法

有时我们需要将多台计算机连接在一起&#xff0c;以便实现数据共享、资源访问等功能。本文将介绍如何通过网线连接两台运行Ubuntu操作系统的电脑&#xff0c;以便它们能够直接通信&#xff0c;从而实现局域网连接。 1. 准备工作 在开始之前&#xff0c;请准备好&#xff1a; …

2024牛客寒假算法基础集训营4(视频讲解题目)

2024牛客寒假算法基础集训营4&#xff08;视频讲解题目&#xff09; 视频链接ABCDEFG、H&#xff08;下面是hard版本的代码两个都可以过&#xff09; 视频链接 2024牛客寒假算法基础集训营4&#xff08;视频讲解题目&#xff09; A #include<bits/stdc.h> #define en…

深入探索pdfplumber:从PDF中提取信息到实际项目应用【第94篇—pdfplumbe】

深入探索pdfplumber&#xff1a;从PDF中提取信息到实际项目应用 在数据处理和信息提取的过程中&#xff0c;PDF文档是一种常见的格式。然而&#xff0c;要从PDF中提取信息并进行进一步的分析&#xff0c;我们需要使用适当的工具。本文将介绍如何使用Python库中的pdfplumber库来…

华为OD机试真题-整数对最小和-2023年OD统一考试(C卷)-- Python3-开源

题目&#xff1a; 考察内容&#xff1a;双循环sortsum 代码&#xff1a; """ 题目分析&#xff1a; 求随机组合最小和 输入&#xff1a; 数组a个数&#xff0c; 数组元素 数组b个数&#xff0c;数组元素 对数个数输出&#xff1a; 和的最小值3 1 1 2 3 1 2 3…

时间获取、文件属性获取 2月20日学习笔记

执行两次代码&#xff0c;打印出两次执行过程中新增的文件及删除的文件 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <dirent.h>#def…

Docker容器实战

"爱在&#xff0c;地图上&#xff0c;剥落~" Mysql 容器化安装 我们可以在 docker hub上&#xff0c;进入mysql的镜像仓库&#xff0c;找到适合的版本。 直接拉取镜像: docker pull mysql:latest 我们知道 msyql 的默认端口是 3306 &#xff0c;而且有密码&#x…

MYSQL-入门

一.安装和连接 1.1 安装 mysql安装教程&#xff1a; 2021MySql-8.0.26安装详细教程&#xff08;保姆级&#xff09;_2021mysql-8.0.26安装详细教程(保姆级)_mysql8.0.26_ylb呀的博客-cs-CSDN博客 workbench安装&#xff1a; MySQL Workbench 安装及使用-CSDN博客 1.2 配…

强大的文本绘图——PlantUML

PlantUML是一款开源工具&#xff0c;它允许用户通过简单的文本描述来创建UML图&#xff08;统一建模语言图&#xff09;。这种方法可以快速地绘制类图、用例图、序列图、状态图、活动图、组件图和部署图等UML图表。PlantUML使用一种领域特定语言&#xff08;DSL&#xff09;&am…

本机防攻击简介

定义 在网络中&#xff0c;存在着大量针对CPU&#xff08;Central Processing Unit&#xff09;的恶意攻击报文以及需要正常上送CPU的各类报文。针对CPU的恶意攻击报文会导致CPU长时间繁忙的处理攻击报文&#xff0c;从而引发其他业务的中断甚至系统的中断&#xff1b;大量正常…

idea如何在一个service窗口中显示多个服务教程

idea在service窗口中显示多个服务 展示效果如下: 找到.idea > workspace.xml 中找到 RunDashboard 替换成如下 <component name"RunDashboard"><option name"configurationTypes"><set><option value"SpringBootApplicatio…

反序列化字符串逃逸 [安洵杯 2019]easy_serialize_php1

打开题目 $_SESSION是访客与整个网站交互过程中一直存在的公有变量 然后看extract()函数的功能&#xff1a; extract($_POST)就是将post的内容作为这个函数的参数。 extract() 函数从数组中将变量导入到当前的符号表(本题的作用是将_SESSION的两个函数变为post传参) function…

【鸿蒙 HarmonyOS 4.0】状态管理

一、介绍 资料来自官网&#xff1a;文档中心 在声明式UI编程框架中&#xff0c;UI是程序状态的运行结果&#xff0c;用户构建了一个UI模型&#xff0c;其中应用的运行时的状态是参数。当参数改变时&#xff0c;UI作为返回结果&#xff0c;也将进行对应的改变。这些运行时的状…

氢气传感器与氢冷发电机:氢能应用中的关键技术及其安全监测

​ ​随着全球对可再生能源的迫切需求&#xff0c;氢能作为一种清洁、高效的能源形式&#xff0c;正逐渐受到人们的青睐。在氢能利用的过程中&#xff0c;氢气传感器和氢冷发电机成为了不可或缺的关键技术。然而&#xff0c;氢气作为一种易燃易爆的气体&#xff0c;其安全使…

P8630 [蓝桥杯 2015 国 B] 密文搜索

P8630 [蓝桥杯 2015 国 B] 密文搜索 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P8630 题目分析 基本上是hash的板子&#xff0c;但实际上对于密码串&#xff0c;只要判断主串中任意连续的八个位置是否存在密码串即可&#xff1b;那么我们…

svn客户端下载、安装、使用

下载、使用 打开360软件管家&#xff0c;选怎宝库&#xff0c;搜索svn&#xff0c;点击安装 可以修改安装路径 使用 在桌面右键弹出菜单&#xff0c;点击 输入地址&#xff0c;点击ok 输入用户名、密码 &#xff0c;等待检出完成

机器学习基础(四)非监督学习的进阶探索

导语&#xff1a;上一节我们详细探索监督学习的进阶应用&#xff0c;详情可见&#xff1a; 机器学习基础&#xff08;三&#xff09;监督学习的进阶探索-CSDN博客文章浏览阅读296次&#xff0c;点赞13次&#xff0c;收藏11次。监督学习作为机器学习的一个主要分支&#xff0c;…

基础中的基础!吴恩达deeplearning.ai:如何搭建一个神经网络

在前面几篇博客的学习之后&#xff0c;你应该了解了如何写出Tensorflow有关的代码&#xff0c;如何在Tensorflow中搭建一个层以及如何在Tensorflow之中实现前向推理&#xff08;链接&#xff09;&#xff0c;也了解了Tensorflow有关的数据形式&#xff08;链接&#xff09; 今天…

深度学习介绍

02-深度学习介绍 1 AI地图2 深度学习任务2.1 图片分类2.2 物体检测和分割2.3 样式迁移2.4 人脸合成2.5 文字生成图片2.6 文字生成2.7 无人驾驶 3 案例研究4 question 1 AI地图 自然语言处理是感知的范围&#xff0c;人几秒内科研感知。 2 深度学习任务 2.1 图片分类 https:/…
推荐文章