news 2026/7/28 11:16:09

Zookeeper--08---zk实现分布式锁、案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Zookeeper--08---zk实现分布式锁、案例

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • zk实现分布式锁
    • 1.zk中锁的种类:
    • 2.zk如何上读锁
    • 3.zk如何上写锁
    • 4.⽺群效应
        • 可以调整成链式监听。解决这个问题。
    • 5.curator实现读写锁
  • 分布式锁案例
    • 案例分析
    • 依赖:
    • 分布式锁原理--序号节点
        • 持久序号节点
        • 临时序号节点
    • 分布式锁实现
    • 测试
    • 对比单体模式下---ReentrantLock
  • Curator框架实现分布式锁案例
    • 依赖
    • 获取客户端连接
    • 测试案例
  • 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{// 读写锁InterProcessReadWriteLockinterProcessReadWriteLock=newInterProcessReadWriteLock(client,"/lock1");// 获取读锁对象InterProcessLockinterProcessLock=interProcessReadWriteLock.readLock();System.out.println("等待获取读锁对象!");// 获取锁interProcessLock.acquire();for(inti=1;i<=100;i++){Thread.sleep(3000);System.out.println(i);}// 释放锁interProcessLock.release();System.out.println("等待释放锁!");}@TestvoidtestGetWriteLock()throwsException{// 读写锁InterProcessReadWriteLockinterProcessReadWriteLock=newInterProcessReadWriteLock(client,"/lock1");// 获取写锁对象InterProcessLockinterProcessLock=interProcessReadWriteLock.writeLock();System.out.println("等待获取写锁对象!");// 获取锁interProcessLock.acquire();for(inti=1;i<=100;i++){Thread.sleep(3000);System.out.println(i);}// 释放锁interProcessLock.release();System.out.println("等待释放锁!");}}

分布式锁案例

案例分析

  • 比如说 "进程 1"在使用该资源的时候,会先去获得锁在使用该资源的时候,保持独占,这样其他进程就无法访问该资源,
  • "进程1"用完该资源以后就将锁释放掉,让其他进程来获得锁,
  • 那么通过这个锁机制,我们就能保证了分布式系统中多个进程能够有序的访问该临界资源。那么我们把这个分布式环境下的这个锁叫作分布式锁。

  1. 接收到请求后,在/locks节点下创建一个临时顺序节点
  2. 判断自己是不是当前节点下最小的节点:是,获取到锁;不是,对前一个节点进行监听
  3. 获取到锁,处理完业务后,delete节点释放锁,然后下面的节点将收到通知,重复第二步判断

依赖:

<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.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{privatefinalStringconnectString="hadoop102:2181,hadoop103:2181,hadoop104:2181";privatefinalintsessionTimeout=2000;privatefinalZooKeeperzk;privateCountDownLatchconnectLatch=newCountDownLatch(1);privateCountDownLatchwaitLatch=newCountDownLatch(1);privateStringwaitPath;privateStringcurrentMode;publicDistributedLock()throwsIOException,InterruptedException,KeeperException{// 获取连接zk=newZooKeeper(connectString,sessionTimeout,newWatcher(){@Overridepublicvoidprocess(WatchedEventwatchedEvent){// connectLatch 如果连接上zk 可以释放if(watchedEvent.getState()==Event.KeeperState.SyncConnected){connectLatch.countDown();}// waitLatch 需要释放if(watchedEvent.getType()==Event.EventType.NodeDeleted&&watchedEvent.getPath().equals(waitPath)){waitLatch.countDown();}}});// 等待zk正常连接后,往下走程序connectLatch.await();// 判断根节点/locks是否存在Statstat=zk.exists("/locks",false);if(stat==null){// 创建一下根节点zk.create("/locks","locks".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);}}// 对zk加锁publicvoidzklock(){// 创建对应的临时带序号节点try{currentMode=zk.create("/locks/"+"seq-",null,ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);// wait一小会, 让结果更清晰一些Thread.sleep(10);// 判断创建的节点是否是最小的序号节点,如果是获取到锁;如果不是,监听他序号前一个节点List<String>children=zk.getChildren("/locks",false);// 如果children 只有一个值,那就直接获取锁; 如果有多个节点,需要判断,谁最小if(children.size()==1){return;}else{Collections.sort(children);// 获取节点名称 seq-00000000StringthisNode=currentMode.substring("/locks/".length());// 通过seq-00000000获取该节点在children集合的位置intindex=children.indexOf(thisNode);// 判断if(index==-1){System.out.println("数据异常");}elseif(index==0){// 就一个节点,可以获取锁了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{finalDistributedLocklock1=newDistributedLock();finalDistributedLocklock2=newDistributedLock();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();}}

对比单体模式下—ReentrantLock

Curator框架实现分布式锁案例

依赖

<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>4.3.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.3.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-client</artifactId><version>4.3.0</version></dependency>

获取客户端连接

privatestaticCuratorFrameworkgetCuratorFramework(){ExponentialBackoffRetrypolicy=newExponentialBackoffRetry(3000,3);CuratorFrameworkclient=CuratorFrameworkFactory.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){// 创建分布式锁1InterProcessMutexlock1=newInterProcessMutex(getCuratorFramework(),"/locks");// 创建分布式锁2InterProcessMutexlock2=newInterProcessMutex(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(){ExponentialBackoffRetrypolicy=newExponentialBackoffRetry(3000,3);CuratorFrameworkclient=CuratorFrameworkFactory.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分布式锁的实现

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/28 11:16:04

企业级Agentic AI落地指南:从概念到实践,构建自主数字员工

最近和几个做企业数字化转型的朋友聊天,发现一个很有意思的现象:大家嘴上都在聊“Agentic AI”(智能体AI),但具体到落地,十个人有十个不同的理解。有人觉得就是给ChatGPT加个API调用,有人认为是自动化流程的升级版,还有人把它等同于RPA(机器人流程自动化)的AI化。 这…

作者头像 李华
网站建设 2026/7/28 11:16:02

如何避免五年经验重复一年?技术人成长突破指南

1. 项目概述&#xff1a;五年经验的血泪教训 "五年经验&#xff0c;1200个小时&#xff0c;全浪费在同一个地方"这个标题背后&#xff0c;隐藏着许多职场人共同的痛点。作为一名经历过类似困境的从业者&#xff0c;我深刻理解这种挫败感——投入大量时间精力却发现自…

作者头像 李华
网站建设 2026/7/28 11:15:37

计算机毕业设计之基于SpringBoot的高校就业管理系统

随着新世纪无纸化办公方式的普及&#xff0c;自动化信息处理和基于网络的信息交互方式已被广泛应用。现在很多行业基本上都是交由计算机进行管理和测试&#xff0c;网络与计算机已成为整个线上管理体系中的重要组成部分。虽然信息技术广泛应用和数据存取更加方便&#xff0c;但…

作者头像 李华
网站建设 2026/7/28 11:15:16

物联网安全:SE050安全元件与TM4C1294NCPDT的协同设计

1. 物联网安全现状与SE050的定位 在万物互联的时代&#xff0c;物联网设备数量呈指数级增长&#xff0c;但安全防护水平却严重滞后。根据行业调研数据&#xff0c;超过70%的IoT设备存在中高危漏洞&#xff0c;而传统MCU在应对密钥存储、安全启动、加密运算等核心安全需求时往往…

作者头像 李华
网站建设 2026/7/28 11:14:31

NBM5100A与STM32F723IE的低功耗物联网电源管理方案

1. 项目背景与核心价值在物联网和低功耗设备设计中&#xff0c;电池寿命和瞬时电流供应能力一直是工程师面临的两大挑战。传统锂原电池&#xff08;如Li-SOCl₂&#xff09;虽然能量密度高&#xff0c;但在应对无线模块、传感器等设备的突发负载时&#xff0c;会出现明显的电压…

作者头像 李华
网站建设 2026/7/28 11:14:19

Fnet 云网安 260728

&#x1f6e1;️ NSOC&#xff08;网络安全云一体化运营中心&#xff09; 724主动监控与专家值守&#xff0c;网络可用性99.99%&#xff0c;安全事件100%闭环&#xff0c;云资源一站式管理 今日热点 Top 5 S1 Hermes AI Agent被用于泰国财政部无人值守后渗透&#xff1a;攻击…

作者头像 李华