Zookeeper--08---zk实现分布式锁、案例
提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录zk实现分布式锁1.zk中锁的种类2.zk如何上读锁3.zk如何上写锁4.⽺群效应可以调整成链式监听。解决这个问题。5.curator实现读写锁分布式锁案例案例分析依赖分布式锁原理--序号节点持久序号节点临时序号节点分布式锁实现测试对比单体模式下---ReentrantLockCurator框架实现分布式锁案例依赖获取客户端连接测试案例Redis分布式锁的实现zk实现分布式锁1.zk中锁的种类读锁⼤家都可以读要想上读锁的前提之前的锁没有写锁写锁只有得到写锁的才能写。要想上写锁的前提是之前没有任何锁。2.zk如何上读锁1.创建⼀个临时序号节点节点的数据是read表示是读锁2.获取当前zk中序号⽐⾃⼰⼩的所有节点3.判断最⼩节点是否是读锁如果不是读锁的话则上锁失败为最⼩节点设置监听。阻塞等待zk的watch机制会当最⼩节点发⽣变化时通知当前节点于是再执⾏第⼆步的流程如果是读锁的话则上锁成功3.zk如何上写锁1.创建⼀个临时序号节点节点的数据是write表示是 写锁2.获取zk中所有的⼦节点3.判断⾃⼰是否是最⼩的节点如果是则上写锁成功如果不是说明前⾯还有锁则上锁失败监听最⼩的节点如果最⼩节点有变化 则回到第⼆步。4.⽺群效应如果⽤上述的上锁⽅式只要有节点发⽣变化就会触发其他节点的监听事件这样的话对zk的压⼒⾮常⼤——⽺群效应。可以调整成链式监听。解决这个问题。5.curator实现读写锁importorg.apache.curator.framework.CuratorFramework;importorg.apache.curator.framework.recipes.locks.InterProcessLock;importorg.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;SpringBootTestpublicclassTestReadWriteLock{AutowiredprivateCuratorFrameworkclient;TestvoidtestGetReadLock()throwsException{// 读写锁InterProcessReadWriteLockinterProcessReadWriteLocknewInterProcessReadWriteLock(client,/lock1);// 获取读锁对象InterProcessLockinterProcessLockinterProcessReadWriteLock.readLock();System.out.println(等待获取读锁对象!);// 获取锁interProcessLock.acquire();for(inti1;i100;i){Thread.sleep(3000);System.out.println(i);}// 释放锁interProcessLock.release();System.out.println(等待释放锁!);}TestvoidtestGetWriteLock()throwsException{// 读写锁InterProcessReadWriteLockinterProcessReadWriteLocknewInterProcessReadWriteLock(client,/lock1);// 获取写锁对象InterProcessLockinterProcessLockinterProcessReadWriteLock.writeLock();System.out.println(等待获取写锁对象!);// 获取锁interProcessLock.acquire();for(inti1;i100;i){Thread.sleep(3000);System.out.println(i);}// 释放锁interProcessLock.release();System.out.println(等待释放锁!);}}分布式锁案例案例分析比如说 进程 1在使用该资源的时候会先去获得锁在使用该资源的时候保持独占这样其他进程就无法访问该资源进程1用完该资源以后就将锁释放掉让其他进程来获得锁那么通过这个锁机制我们就能保证了分布式系统中多个进程能够有序的访问该临界资源。那么我们把这个分布式环境下的这个锁叫作分布式锁。接收到请求后在/locks节点下创建一个临时顺序节点判断自己是不是当前节点下最小的节点是获取到锁不是对前一个节点进行监听获取到锁处理完业务后delete节点释放锁然后下面的节点将收到通知重复第二步判断依赖dependencygroupIdorg.apache.zookeeper/groupIdartifactIdzookeeper/artifactIdversion3.5.7/version/dependency分布式锁原理–序号节点持久序号节点临时序号节点分布式锁实现获取连接对zk加锁对zk解锁importorg.apache.zookeeper.*;importorg.apache.zookeeper.data.Stat;importjava.io.IOException;importjava.util.Collections;importjava.util.List;importjava.util.concurrent.CountDownLatch;publicclassDistributedLock{privatefinalStringconnectStringhadoop102:2181,hadoop103:2181,hadoop104:2181;privatefinalintsessionTimeout2000;privatefinalZooKeeperzk;privateCountDownLatchconnectLatchnewCountDownLatch(1);privateCountDownLatchwaitLatchnewCountDownLatch(1);privateStringwaitPath;privateStringcurrentMode;publicDistributedLock()throwsIOException,InterruptedException,KeeperException{// 获取连接zknewZooKeeper(connectString,sessionTimeout,newWatcher(){Overridepublicvoidprocess(WatchedEventwatchedEvent){// connectLatch 如果连接上zk 可以释放if(watchedEvent.getState()Event.KeeperState.SyncConnected){connectLatch.countDown();}// waitLatch 需要释放if(watchedEvent.getType()Event.EventType.NodeDeletedwatchedEvent.getPath().equals(waitPath)){waitLatch.countDown();}}});// 等待zk正常连接后往下走程序connectLatch.await();// 判断根节点/locks是否存在Statstatzk.exists(/locks,false);if(statnull){// 创建一下根节点zk.create(/locks,locks.getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);}}// 对zk加锁publicvoidzklock(){// 创建对应的临时带序号节点try{currentModezk.create(/locks/seq-,null,ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);// wait一小会, 让结果更清晰一些Thread.sleep(10);// 判断创建的节点是否是最小的序号节点如果是获取到锁如果不是监听他序号前一个节点ListStringchildrenzk.getChildren(/locks,false);// 如果children 只有一个值那就直接获取锁 如果有多个节点需要判断谁最小if(children.size()1){return;}else{Collections.sort(children);// 获取节点名称 seq-00000000StringthisNodecurrentMode.substring(/locks/.length());// 通过seq-00000000获取该节点在children集合的位置intindexchildren.indexOf(thisNode);// 判断if(index-1){System.out.println(数据异常);}elseif(index0){// 就一个节点可以获取锁了return;}else{// 需要监听 他前一个节点变化waitPath/locks/children.get(index-1);zk.getData(waitPath,true,newStat());// 等待监听waitLatch.await();return;}}}catch(KeeperExceptione){e.printStackTrace();}catch(InterruptedExceptione){e.printStackTrace();}}// 解锁publicvoidunZkLock(){// 删除节点try{zk.delete(this.currentMode,-1);}catch(InterruptedExceptione){e.printStackTrace();}catch(KeeperExceptione){e.printStackTrace();}}}测试importorg.apache.zookeeper.KeeperException;importjava.io.IOException;publicclassDistributedLockTest{publicstaticvoidmain(String[]args)throwsInterruptedException,IOException,KeeperException{finalDistributedLocklock1newDistributedLock();finalDistributedLocklock2newDistributedLock();newThread(newRunnable(){Overridepublicvoidrun(){try{lock1.zklock();System.out.println(线程1 启动获取到锁);Thread.sleep(5*1000);lock1.unZkLock();System.out.println(线程1 释放锁);}catch(InterruptedExceptione){e.printStackTrace();}}}).start();newThread(newRunnable(){Overridepublicvoidrun(){try{lock2.zklock();System.out.println(线程2 启动获取到锁);Thread.sleep(5*1000);lock2.unZkLock();System.out.println(线程2 释放锁);}catch(InterruptedExceptione){e.printStackTrace();}}}).start();}}对比单体模式下—ReentrantLockCurator框架实现分布式锁案例依赖dependencygroupIdorg.apache.curator/groupIdartifactIdcurator-framework/artifactIdversion4.3.0/version/dependencydependencygroupIdorg.apache.curator/groupIdartifactIdcurator-recipes/artifactIdversion4.3.0/version/dependencydependencygroupIdorg.apache.curator/groupIdartifactIdcurator-client/artifactIdversion4.3.0/version/dependency获取客户端连接privatestaticCuratorFrameworkgetCuratorFramework(){ExponentialBackoffRetrypolicynewExponentialBackoffRetry(3000,3);CuratorFrameworkclientCuratorFrameworkFactory.builder().connectString(hadoop102:2181,hadoop103:2181,hadoop104:2181).connectionTimeoutMs(2000).sessionTimeoutMs(2000).retryPolicy(policy).build();// 启动客户端client.start();System.out.println(zookeeper 启动成功);returnclient;}测试案例importorg.apache.curator.framework.CuratorFramework;importorg.apache.curator.framework.CuratorFrameworkFactory;importorg.apache.curator.framework.recipes.locks.InterProcessMutex;importorg.apache.curator.retry.ExponentialBackoffRetry;publicclassCuratorLockTest{publicstaticvoidmain(String[]args){// 创建分布式锁1InterProcessMutexlock1newInterProcessMutex(getCuratorFramework(),/locks);// 创建分布式锁2InterProcessMutexlock2newInterProcessMutex(getCuratorFramework(),/locks);newThread(newRunnable(){Overridepublicvoidrun(){try{lock1.acquire();System.out.println(线程1 获取到锁);lock1.acquire();System.out.println(线程1 再次获取到锁);Thread.sleep(5*1000);lock1.release();System.out.println(线程1 释放锁);lock1.release();System.out.println(线程1 再次释放锁);}catch(Exceptione){e.printStackTrace();}}}).start();newThread(newRunnable(){Overridepublicvoidrun(){try{lock2.acquire();System.out.println(线程2 获取到锁);lock2.acquire();System.out.println(线程2 再次获取到锁);Thread.sleep(5*1000);lock2.release();System.out.println(线程2 释放锁);lock2.release();System.out.println(线程2 再次释放锁);}catch(Exceptione){e.printStackTrace();}}}).start();}privatestaticCuratorFrameworkgetCuratorFramework(){ExponentialBackoffRetrypolicynewExponentialBackoffRetry(3000,3);CuratorFrameworkclientCuratorFrameworkFactory.builder().connectString(hadoop102:2181,hadoop103:2181,hadoop104:2181).connectionTimeoutMs(2000).sessionTimeoutMs(2000).retryPolicy(policy).build();// 启动客户端client.start();System.out.println(zookeeper 启动成功);returnclient;}}Redis分布式锁的实现Redis–12–Redis分布式锁的实现

相关新闻

Keil5 修改STM32单片机项目名称

Keil5 修改STM32单片机项目名称

Keil5 修改STM32单片机项目名称 目录 Keil5 修改STM32单片机项目名称引言步骤1、修改文件夹名称2、删除修改项目文件3、打开项目中修改属性4、修改输出文件名5、编译引言 在做STM32单片机的时候经常要移植工程或者例程。需要修改工程名称,百度的很多方法说的不清楚有…

2026/9/27 15:46:27 阅读更多 →
docker的基本操作命令

docker的基本操作命令

目录:1、镜像相关操作2、镜像复制(cp)3、日志(logs)查询3.1、通过时间点过滤日志4、查看 Docker 版本(version)查看 Docker 客户端和服务端版本信息。5、查看 Docker 系统信息(info)查看 Docker 运行环境信息。6、查看…

2026/10/10 3:28:23 阅读更多 →
计算机毕业设计之基于Javaweb的肇庆旅游系统的设计与实现lw

计算机毕业设计之基于Javaweb的肇庆旅游系统的设计与实现lw

本世纪以来,随着越来越多的人使用网络,互联网得到了极大的发展,各种网络资源呈一个爆发性的增长,越来越多的人通过各种各样的网络工具,例如一些专业旅游的网站,查询各种各样的信息,为了适应社会…

2026/10/1 11:34:00 阅读更多 →

最新新闻

UCINET数据导入实战:格式规范、Excel整理与高频排错

UCINET数据导入实战:格式规范、Excel整理与高频排错

1. 先搞清楚UCINET到底在等什么数据很多人在UCINET上栽的第一个跟头,不是不会跑算法,而是数据根本喂不进去。明明Excel里填得工工整整,一点Import却报错,或者导进去之后变成一团乱麻,节点对不上、值全错位。这些问题的…

2026/10/13 4:57:19 阅读更多 →
上班族碎片时间做小红书:工位运营全攻略,高效副业不焦虑

上班族碎片时间做小红书:工位运营全攻略,高效副业不焦虑

开头作为一个常年白天在公司坐班、晚上回家还想搞点副业的运营人,我发现周围越来越多同事开始把小红书当成一个“工作之外的第二战场”。但很多人卡在同一个地方:不是不会写文案,也不是不懂拍照,而是总觉得“没时间”——上班忙成…

2026/10/13 4:57:19 阅读更多 →
InterviewGuide 力扣刷题笔记:80. 删除排序数组中的重复项 II——原地去重的双指针通用解法

InterviewGuide 力扣刷题笔记:80. 删除排序数组中的重复项 II——原地去重的双指针通用解法

文档教程知识库 【免费下载链接】InterviewGuide 🔥🔥「InterviewGuide」是阿秀从校园->职场多年计算机自学过程的记录以及学弟学妹们计算机校招&秋招经验总结文章的汇总,包括但不限于C/C 、Golang、JavaScript、Vue、操作系统、数据结…

2026/10/13 4:57:19 阅读更多 →
AnyPS5:PS5存储扩展、外设兼容与网络优化全攻略

AnyPS5:PS5存储扩展、外设兼容与网络优化全攻略

说实话,一开始想做“AnyPS5”这个项目的动机挺简单的:我自己手头有几台不同批次、不同使用时长、甚至连摆放环境都完全不一样PS5主机。有朋友来家里玩,都会问同样的问题——为什么我这台开游戏就是快一点?为什么他那台插个手柄总是…

2026/10/13 4:57:19 阅读更多 →
Hermes Agent入门:轻量级协议语义翻译器实战指南

Hermes Agent入门:轻量级协议语义翻译器实战指南

1. 为什么“Hermes Agent”突然被大量开发者同时提及?最近两周,我在几个技术交流群和内部项目复盘会上,连续听到不同背景的开发者提到同一个词:Hermes Agent。不是Hermes引擎、不是React Native的Hermes JS引擎,而是带…

2026/10/13 4:57:19 阅读更多 →
Android ANR问题全链路分析:从判定机制到测试解决方案

Android ANR问题全链路分析:从判定机制到测试解决方案

我最早接触ANR,是线上用户反馈一个列表页“点了没反应”,过一会儿系统弹窗“进程无响应”。当时拿着一个logcat日志,翻来覆去只能看到一行“ANR in”,完全不知道怎么下手。后来带测试团队、又参与线上性能治理,踩了无数…

2026/10/13 4:56:18 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →