原理

多个客户端抢一把锁,这些客户端在 zookeeper 里创建各自的临时序列node,无论什么顺序,阻塞住,直到找到第一个创建的节点才放开,即第一个客户端获得了锁,不是第一个的客户端,就阻塞,直到第一个客户端运行结束,删除他创建的节点,让剩下的客户端继续轮循直到找到第一个的过程。

结果展示

用10个线程模拟10个客户端的结果如下:

代码

package org.faithgreen.lock1;import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;public class LockWatchCallBack1 implements Watcher, AsyncCallback.StatCallback, AsyncCallback.ChildrenCallback, AsyncCallback.StringCallback {private ZooKeeper zk;private String threadName;private String pathName;private CountDownLatch latch = new CountDownLatch(1);public ZooKeeper getZk() {return zk;}public void setZk(ZooKeeper zk) {this.zk = zk;}public String getThreadName() {return threadName;}public void setThreadName(String threadName) {this.threadName = threadName;}public String getPathName() {return pathName;}public void setPathName(String pathName) {this.pathName = pathName;}/*** 创建 CreateMode.EPHEMERAL_SEQUENTIAL 节点,阻塞*/public void tryLock() {zk.create("/lock", threadName.getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL, this, "abc");try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}}/*** zk.create 的 StringCallBack impl* 如果创建完了,这个回调会被调用,获取children** @param rc* @param path* @param o* @param childPath*/@Overridepublic void processResult(int rc, String path, Object o, String childPath) {if (childPath != null) {System.out.println(childPath + " created");pathName = childPath;zk.getChildren("/", this, this, "dev");}}/*** 获取 children 的回调* 多个客户端创建节点,list 总是有第一个的,如果是第一个,线程放行,否则在前一个节点上添加 watcher** @param rc* @param s* @param o* @param list*/@Overridepublic void processResult(int rc, String s, Object o, List<String> list) {//        Collections.sort(list);int i = list.indexOf(pathName.substring(1));if (i == 0) {// 是第一个,就对了,获取锁了System.out.println(threadName + " is first ....");latch.countDown();} else {// 不是第一个,就在他的前一个加 watcherzk.exists("/" + list.get(i - 1), this, this, "dev");}}/*** children 节点的 watcher* 在释放锁是删除节点的时候触发再一次获取 children 的过程** @param e*/@Overridepublic void process(WatchedEvent e) {switch (e.getType()) {case None:break;case NodeCreated:break;case NodeDeleted:zk.getChildren("/", false, this, "dadd");break;case NodeDataChanged:break;case NodeChildrenChanged:break;}}@Overridepublic void processResult(int i, String s, Object o, Stat stat) {}/*** 释放锁的时候,删除节点*/public void unLock() {try {System.out.println(threadName + "工作结束,释放锁 ....");zk.delete(pathName, -1);} catch (InterruptedException e) {e.printStackTrace();} catch (KeeperException e) {e.printStackTrace();}}
}
package org.faithgreen.lock1;import org.apache.zookeeper.ZooKeeper;
import org.faithgreen.conf1.ZooKeeperUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;public class TestLock1 {ZooKeeper zk;@Beforepublic void getZk() {zk = ZooKeeperUtils.getZk();}@Afterpublic void after() {try {zk.close();} catch (InterruptedException e) {e.printStackTrace();}}@Testpublic void lock() {for (int i = 0; i < 10; i++) {new Thread(() -> {LockWatchCallBack1 w = new LockWatchCallBack1();String name = Thread.currentThread().getName();w.setThreadName(name);w.setZk(zk);// 获取锁w.tryLock();// 模拟客户端得到锁之后的工作System.out.println(name + " working ...");// 释放锁w.unLock();}).start();}try {System.in.read();} catch (IOException e) {e.printStackTrace();}}
}
package org.faithgreen.conf1;import org.apache.zookeeper.ZooKeeper;import java.io.IOException;
import java.util.concurrent.CountDownLatch;public class ZooKeeperUtils {static ZooKeeper zk;final static String address = "192.168.172.3:2181,192.168.172.4:2181,192.168.172.5:2181,192.168.172.6:2181/testLock";static CountDownLatch latch = new CountDownLatch(1);static DefaultWatcher defaultWatcher = new DefaultWatcher();public static ZooKeeper getZk() {ZooKeeper zk = null;try {zk = new ZooKeeper(address, 3000, defaultWatcher);defaultWatcher.setLatch(latch);latch.await();} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}return zk;}}

zookeeper做分布式锁相关推荐

  1. 浅析redis与zookeeper构建分布式锁的异同

    作者:架构小菜 链接:https://www.jianshu.com/p/508620a76e00 进程请求分布式锁时一般包含三个阶段:1. 进程请求获取锁:2. 获取到锁的进程持有锁并执行业务逻辑: ...

  2. 基于 Zookeeper 的分布式锁实现

    1. 背景 最近在学习 Zookeeper,在刚开始接触 Zookeeper 的时候,完全不知道 Zookeeper 有什么用.且很多资料都是将 Zookeeper 描述成一个"类 Unix ...

  3. zookeeper专题:使用zookeeper实现分布式锁

    文章目录 1. zookeeper为什么可以做分布式锁 ? 2. zookeeper实现非公平锁 3. zookeeper实现公平锁 4. zookeeper实现读写锁(共享锁) 5. Curator ...

  4. 基于Zookeeper的分布式锁

    实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...

  5. 22-09-20 西安 谷粒商城(04)Redisson做分布式锁、布隆过滤器、AOP赋能、自定义注解做缓存管理、秒杀测试

    Redisson 1.Redisson做分布式锁  分布式锁主流的实现方案: 基于数据库实现分布式锁 基于缓存(Redis),性能最高 基于Zookeeper,可靠性最高 Redisson是一个在Re ...

  6. 基于ZooKeeper的分布式锁和队列

    分布式锁的几种实现: 1.zookeeper分布式锁,基于自增节点 2.Redis分布式锁,基于setnx命令, 基于Redis实现分布式锁:http://blog.csdn.net/daiyudon ...

  7. 利用Zookeeper实现 - 分布式锁

    微信原文: 利用Zookeeper实现 - 分布式锁 博客原文:利用Zookeeper实现 - 分布式锁 在许多场景中,数据一致性是一个比较重要的话题,在单机环境中,我们可以通过Java提供的并发AP ...

  8. 分布式锁和数据一致性的讨论——redis集群做分布式锁的风险

    文章目录 写在前面 分布式锁的三个属性 分布式锁就⼀定要实现这三个属性吗? 实现容错性 方法一:基于多个 Redis 节点实现分布式锁 问题一:进程可能会被挂起,直到锁的 TTL 过期 问题二:墙上时 ...

  9. redis做分布式锁可能不那么简单

    在计算机世界里,对于锁大家并不陌生,在现代所有的语言中几乎都提供了语言级别锁的实现,为什么我们的程序有时候会这么依赖锁呢?这个问题还是要从计算机的发展说起,随着计算机硬件的不断升级,多核cpu,多线程 ...

最新文章

  1. Squid3反向代理安装与配置
  2. 用Python轻松搞定Excel中的20个常用操作
  3. 不用ajax 后台的异步实现,js 怎么避免重复的异步操作(不问了,目前没办法后台做到,只能改造前端了)...
  4. mysqldiff对比主从表结构是否一致
  5. HDU 2149 Public Sale
  6. TF之DD:利用Inception模型+GD算法生成带背景的大尺寸、高质量的Deep Dream图片
  7. 图文解释Glados自动签到免费获取天数(github action版)
  8. 深入浅出SQL(1)
  9. sql java 创建数据库_java动态创建数据库(sql server)
  10. Wannafly挑战赛10F-小H和遗迹【Trie,树状数组】
  11. 十五、导航,头部,CSS基础
  12. 听说做开发的工资随随便便就上10k?
  13. 为什么量子计算会对我们产生威胁?
  14. 【数学】求三角形的外接圆圆心
  15. 前端开发:颜色代码速查表【英文颜色、HEX格式、RGB格式】
  16. rockchip wificountry code
  17. 置信区间,置信水平/置信度
  18. 【Java 8 GC 调优】“代”(Generation)
  19. linuxwindows应急响应
  20. flutter 基础知识点总结

热门文章

  1. java中方法的具体化_我为什么要关心Java没有具体化的泛型?
  2. 教你使用TensorFlow2对阿拉伯语手写字符数据集进行识别
  3. 成都内推 | 腾讯游戏王者荣耀算法团队招聘算法实习生
  4. AI领域最最最稀缺的人才——AI架构师
  5. 语音识别:繁华背后,危机初现
  6. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task3:网络模型结构发展
  7. 深度学习入门之PyTorch学习笔记
  8. Numpy学习-数组的索引
  9. feign直接走熔断_四、Spring Cloud之熔断处理 Hystrix
  10. 【JavaScript代码】使用JavaScript实现简单的区块链(签名+工作量证明机制)