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容器那样进行快速部署.给我五分钟,本文将介绍如何使 ...
随机推荐
- DOM对象和window对象
本文内容: DOM对象 Window 对象 首发日期:2018-05-11 DOM对象: DOM对象主要指代网页内的标签[包括整个网页] 比如:document代表整个 HTML 文档,用来访问页面中 ...
- 有效运维的 on-call 机制
[编者按]本文作者为云告警平台OneAlert负责人,著<云计算与OpenStack>,在IT运营管理.云计算方面从业10多年. 正文 互联网技术的发展,离不开运维支撑工作,没有零bug的 ...
- Android Thread 官方说明
Thread官方说明 https://developer.android.google.cn/reference/java/lang/Thread Thread是程序中执行的线程.Java虚拟机允许应 ...
- 前端AntD框架的upload组件上传图片时遇到的一些坑
前言 本次做后台管理系统,采用的是 AntD 框架.涉及到图片的上传,用的是AntD的 upload 组件. 前端做文件上传这个功能,是很有技术难度的.既然框架给我们提供好了,那就直接用呗.结果用的时 ...
- CentOS基本的命令与快捷建
由于我的计算机在安装linux系统时,计算机出现了问题,并没有安装ubuntu而是安装的centos.虽然两者属于linux的不同版本,但是在具体的操作上大同小异.在学习linux的各种指令和快捷键的 ...
- SQL Server中sys.syslogin中updatedate字段的浅析
在系统视图sys.syslogins中,有createdate与updatedate两个字段,分别表示创建登录名与更新登录名的日期,如果你用updatedate的值来判断一个登录名的权限是否被修改过, ...
- mysql练习----Self join
stops(id, name) route(num,company,pos, stop) stops route id num name company pos stop
- parent.fraInterface.xxxxxx
fraInterface是自己定义的一个frame的名字,是通过在frame标签中设置name属性实现的.以上那句代码就是通过parent这个公共接口在各个frame间,也就是调用拥有同一个父亲的名为 ...
- {windows故障}关于WIN7故障模块StackHash_0a9e解决方法
问题背景:我给同事重装好系统后,想用驱动精灵(网卡版)给新系统安装驱动,但是在安装驱动精灵的过程中老是出现标题的问题,windows停止工作,导致无法安装,最后看到这两个方法后,把网络适配器禁用,然后 ...
- CentOS7安装redis数据库及php-redis扩展
redis 首先把redis安装到服务器中 1.wget http://download.redis.io/redis-stable.tar.gz 下载redis源码 2. tar xvzf redi ...
