zookeeper-分布式锁的代码实现-【每日五分钟搞定大数据】
本文涉及到几个zookeeper简单的知识点,永久节点、有序节点、watch机制。比较基础,熟悉的就别看了跳过这篇吧
- 每个线程在/locks节点下创建一个临时有序节点test_lock_0000000040
- 获得/locks节点下所有子节点A、B、C,排序获得最小值
- 若当前节点B为最小值则获得锁,执行业务逻辑
- 若当前节点B不是最小值则watch比自己小1的节点A,节点A存在则await,否则获得锁
总结:临时有序节点排序后watch比自己小1的节点。

下面看代码
1.线程初始化
创建一个名字为lockName的永久节点(只有永久节点才可以创建子节点)
DistributedLock(String url, String lockName) {
this.lockName = lockName;
try {
zkConn = new ZooKeeper(url, sessionTimeout, this);
if (zkConn.exists(ROOT_LOCK, false) == null)
zkConn.create(ROOT_LOCK, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
} catch (IOException | InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
复习一下:zookeeper的节点有以下几种类型:永久,永久有序,临时,临时有序
public enum CreateMode {
PERSISTENT(0, false, false),
PERSISTENT_SEQUENTIAL(2, false, true),
EPHEMERAL(1, true, false),
EPHEMERAL_SEQUENTIAL(3, true, true);
2.线程尝试获得锁tryLock
创建临时有序节点,会在你的lockName后面加上一串编号,例如/locks/test_lock_0000000035
CURRENT_LOCK = zkConn.create(ROOT_LOCK + "/" + lockName + splitStr, new byte[0],
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
获取当前lockName下的所有子临时节点
List<String> subNodes = zkConn.getChildren(ROOT_LOCK, false);
把名字都取出来放进list排个序
List<String> lockObjects = new ArrayList<>();
for (String node : subNodes) {
String _node = node.split(splitStr)[0];
if (_node.equals(lockName)) lockObjects.add(node);
}
若当前节点为最小节点,则直接获取锁成功
if (CURRENT_LOCK.equals(ROOT_LOCK + "/" + lockObjects.get(0))) {
return true;
}
若不是最小节点,开始等待,见下一步。
3.开始等待锁
获得当前线程需要等待的节点名
- 获得当前节点的节点名即test_lock_0000000035
- 获得当前几点在所有排队等锁的线程中的排序
- 根据排序-1,获得排在自己前面的线程的节点名
String prevNode = CURRENT_LOCK.substring(CURRENT_LOCK.lastIndexOf("/") + 1);
int prevNodePosition = Collections.binarySearch(lockObjects, prevNode);
WAIT_LOCK = lockObjects.get(prevNodePosition - 1);
给exists加上watcher,监控当前线程等待的节点waitLock是否还存在
若存在即stat不为null,当前线程先开始await
同时watch线程也启动了开始监控exists操作
若是exists状态有变化了(即waitLock不存在了)触发watch线程的countDown操作。
countDown操作使当前线程结束waiting,获得锁,开始继续往后执行
private boolean waitForLock(String waitLock, long waitTime) throws KeeperException, InterruptedException {
Stat stat = zkConn.exists(ROOT_LOCK + "/" + waitLock, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (countDownLatch != null) {
countDownLatch.countDown();
}
}
});
if (stat != null) {
System.out.println(Thread.currentThread().getName() + " is waiting for " + ROOT_LOCK + "/" + waitLock);
this.countDownLatch = new CountDownLatch(1);
this.countDownLatch.await(waitTime, TimeUnit.MILLISECONDS);
this.countDownLatch = null;
System.out.println(Thread.currentThread().getName() + " get the lock ");
}
return true;
}
完整的代码可以在我的公众号后台回复9获得,感谢阅读。

zookeeper-分布式锁的代码实现-【每日五分钟搞定大数据】的更多相关文章
- zookeeper核心-zab协议-《每日五分钟搞定大数据》
上篇文章<paxos与一致性>说到zab是在paxos的基础上做了重要的改造,解决了一系列的问题,这一篇我们就来说下这个zab. zab协议的全称是ZooKeeper Atomic Bro ...
- zookeeper-架构设计与角色分工-《每日五分钟搞定大数据》
本篇文章阅读时间5分钟左右 点击看<每日五分钟搞定大数据>完整思维导图 zookeeper作为一个分布式协调系统,很多组件都会依赖它,那么此时它的可用性就非常重要了,那么保证可用性的同 ...
- HDFS-异常大全-《每日五分钟搞定大数据》
点击看<每日五分钟搞定大数据>完整思维导图以及所有文章目录 问题1:Decomminssioning退役datanode(即删除节点) 1.配置exclude: <name>d ...
- zookeeper-操作与应用场景-《每日五分钟搞定大数据》
Zookeeper作为一个分布式协调系统提供了一项基本服务:分布式锁服务,分布式锁是分布式协调技术实现的核心内容.像配置管理.任务分发.组服务.分布式消息队列.分布式通知/协调等,这些应用实际上都是基 ...
- zookeeper-如何修改源码-《每日五分钟搞定大数据》
本篇文章仅仅是起一个抛砖迎玉的作用,举一个如何修改源码的例子.文章的灵感来自 ZOOKEEPER-2784. 提一个问题先 之前的文章讲过zxid的设计,我们先复习下: zxid有64位,分成两部分: ...
- zookeeper-监控与优化-《每日五分钟搞定大数据》
本文的命令和配置都是基于zookeeper-3.4.6版本.优化很多时候都是基于监控的,所以把这两个内容写在了一起,慢慢消化. 监控 简单地说,监控无非就是获取服务的一些指标,再根据实际业务情况给这些 ...
- redis- info调优入门-《每日五分钟搞定大数据》
本文根据redis的info命令查看redis的内存使用情况以及state状态,来观察redis的运行情况以及需要作出的相应优化. info 1.memory used_memory:13409011 ...
- 五分钟搞定Go.js
五分钟搞定Go.js 1.基于html5~因为Go.js是一个依赖于HTML5特性的JavaScript库,所以需要确保您的页面声明它是一个HTML5文档,当然需要加载库 <!DOCTYPE ...
- 五分钟搞定Linux容器
[TechTarget中国原创] Linux容器针对特定工作负载提供了全新的灵活性与可能性.存在很多解决方案,但是没有一个解决方案能够像systemd容器那样进行快速部署.给我五分钟,本文将介绍如何使 ...
随机推荐
- 【Linux高频命令专题(24)】grep
简述 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来.grep全称是Global Regular Expression Print,表示全局正则 ...
- [20181225]12CR2 SQL Plan Directives.txt
[20181225]12CR2 SQL Plan Directives.txt --//12C引入SQL PLAN Directives.12cR1版本会造成大量的动态取样,影响性能.许多人把OPTI ...
- 5. svg学习笔记-坐标系变换
之前我们编写图形元素的时候,编写好了位置大小就是固定的,通过坐标系变换,可以移动缩放,旋转图形,但必须声明的是,进行变换时是图形相对于坐标系的变化,就是图形是不发生变化的,而是坐标系发生了变化,比如缩 ...
- 将web项目部署到阿里云服务器上
一.用eclipse将写好的项目打成war包 1.右键点击项目,选择Export 选择打包之后的路径,点击Finsh. 2.购买阿里云服务器 按下图选择 3.设置云服务器防火墙 4.远程连接云服务器 ...
- oracle 分组函数执行分析
先上例了: select job as "JOB1", avg(sal) as "avg sal" from scott.emp group by " ...
- python中------decode解码出现的0xca问题解决方法
一.错误: 解决方法: #源代码 data = sk.recv(1024) print(str(data,'gbk')) #修改代码 data = sk.recv(1024) print(str(da ...
- IIS 发布ASP.NET MVC 4.0 错误500.21解决办法
由VS2013 写好的MVC 4.0 发布在服务器IIS 上报错500.21,解决办法:尝试多种网上介绍的办法,最后发现还是模块问题.
- 【项目 · Wonderland】会议一 · 可达鸭
[软件工程实践 · 团队项目] 第一次作业 Part 0 · 简 要 目 录 Part 1 · 队 伍 阵 容 Part 2 · 会 议 记 录 相 关 Part 3 · 会 议 讨 论 记 录 Pa ...
- python3编写网络爬虫17-验证码识别
一.验证码识别 1.图形验证码的识别 识别图形验证码需要 tesserocr 库 OCR技术识别(光学字符识别,是指通过扫描字符,然后通过其形状将其翻译成电子文本的过程.)例如 中国知网注册页面 ht ...
- Python闭包和装饰器再复习
闭包 闭包的定义 在一个外函数中定义了一个内函数,并且内函数用到了外部函数的变量,而且外函数的返回值是内函数的引用,这就构成了一个闭包. 一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东 ...
