欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Zookeeper实现分布式锁

时间:2023-07-17

使用zookeeper实现分布式锁是分布式锁的实现方式的一种,相对于redis的实现,zookeeper的显现能够实现锁的获得顺序,不出现死锁等特点,关于zookeeper分布式锁的实现原理大致总结如下:

客户端向zookeeper的某一个持久节点下注册临时有序节点获取该父节点下的所有临时有序节点,将自己刚才注册的临时节点与节点集合的第一个做比较,如果相同则表示自己是第一个注册也就是可以获得锁的,否则,注册比前置节点的监听事件,如果监听到前置节点被删除(即节点状态发生变化),则重新获取节点集合并进行比较

原理性的东西网上很多很全面,现在我贴下代码,做一个简陋的分布式锁的实现

1.下载zookeeper服务器到本地,启动

https://zookeeper.apache.org/releases.html#download

解压缩后,修改conf目录下的zoo_sample.cfg复制为zoo.cfg,修改里面的配置,没有/data和/log目录就新建一个吧

在bin目录下启动zk_server.cmd,然后启动zk_client.cmd客户端来验证下服务器是否已经启动成功

2.pom.xml引入zkclient的客户端jar包

com.101tec zkclient 0.11

3.代码实现

package com.cw.zklock; import org.I0Itec.zkclient.IZkDataListener;import org.I0Itec.zkclient.ZkClient;import org.apache.zookeeper.ZooKeeper; import java.util.Collections;import java.util.List;import java.util.Random;import java.util.concurrent.CountDownLatch; public class ZookeeperLock{ private ZkClient zkClient; private static final String ROOT_PATH="/lock"; private String lockName; private String eNodeName; private String eNodeNo; public ZookeeperLock(String lockName){ zkClient = new ZkClient("localhost:2181",2000); //连接zk this.lockName =ROOT_PATH.concat("/").concat(lockName); //创建持久节点,该节点下后面创建临时有序节点 if (!zkClient.exists(this.lockName)) { zkClient.createPersistent(this.lockName); } } public void lock(){ for (;;) { if (eNodeName == null) { //创建临时有序节点 eNodeName = zkClient.createEphemeralSequential(lockName.concat("/"), System.currentTimeMillis()); eNodeNo=eNodeName.substring(eNodeName.lastIndexOf("/")+1); } List children = zkClient.getChildren(lockName); //节点排序 Collections.sort(children); if (children.size() > 0) { if (children.get(0).equals(eNodeNo)) { //自己创建的就是第一个临时顺序节点,意味着拿到了锁 System.out.println(eNodeNo+"------------》获得了锁"); break; }else { CountDownLatch latch = new CountDownLatch(1); //获取改节点的前一个节点,注册监听事件,并等待 String prevPath= children.get(children.indexOf(eNodeNo)-1); System.out.println(eNodeNo+"注册监听到------》"+prevPath); zkClient.subscribeDataChanges(lockName.concat("/").concat(prevPath), new IZkDataListener() { @Override public void handleDataChange(String s, Object o) throws Exception { latch.countDown(); } @Override public void handleDataDeleted(String s) throws Exception { System.out.println(eNodeNo+"!!!!!!!!!!!被唤醒"); latch.countDown(); } }); try { System.out.println(eNodeNo+"??????????????开始等待"); latch.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } } }else { //异常情况 System.out.println("子节点数据为空,抛出异常"); throw new RuntimeException("获取锁异常"); } } } public void unLock(){ zkClient.delete(eNodeName); zkClient.close(); System.out.println(eNodeNo+"********************释放了锁"); } public static void main(String[] args) { //测试5个线程的争抢 int threadCount=5; CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { Thread thread = new Thread(()->{ try { latch.await(); ZookeeperLock lock = new ZookeeperLock("lockTest"); lock.lock(); //模拟处理业务逻辑 Thread.sleep(1000+ new Random().nextInt(100)*10); lock.unLock(); } catch (InterruptedException e) { e.printStackTrace(); } }); thread.start(); latch.countDown(); } }}

转自:https://www.cnblogs.com/manmanrenshenglu/p/12951321.html

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。