ZooKeeper 分布式共享锁的实现
原创播客,如需转载请注明出处。原文地址:http://www.cnblogs.com/crawl/p/8352919.html
----------------------------------------------------------------------------------------------------------------------------------------------------------
笔记中提供了大量的代码示例,需要说明的是,大部分代码示例都是本人所敲代码并进行测试,不足之处,请大家指正~
本博客中所有言论仅代表博主本人观点,若有疑惑或者需要本系列分享中的资料工具,敬请联系 qingqing_crawl@163.com
GitHub:https://github.com/QingqingQi
-----------------------------------------------------------------------------------------------------------------------------------------------------------
前言:ZooKeeper 是提供少量数据存储和管理的分布式协调服务。适合存储状态管理信息,可以进行数据的读写,同步,提供对数据节点的监听功能。利用 ZooKeeper 可以实现很多功能,比如:Hadoop2.0,使用 Zookeeper 的事件处理确保整个集群只有一个活跃的 NameNode,存储配置信息等;可以利用 ZooKeeper 感知集群中哪台主机宕机或者下线等等。今天介绍另一个常用的功能,利用 Zookeeper 实现分布式共享锁。
一、简要介绍
利用 Zookeeper 实现分布式共享锁,可以做到一次只有指定个数的客户端访问服务器的某些资源。
二、实现步骤
利用 Zookeeper 实现分布式共享锁的步骤大致可以分为以下几步:
1. 客户端上线即向 Zookeeper 注册,创建一把锁
2. 判断是否只有一个客户端工作,若只有一个客户端工作,此客户端可以处理业务
3. 获取父节点下注册的所有锁,通过判断自己是否是号码最小的那一把锁,若是则可以处理业务,否则等待
值的注意的是,在某一客户端获取到锁处理完业务后,必须释放锁
三、实现代码
1. 新建一个 DistributedLock 类
private ZooKeeper zkClient = null;
//连接字符串
private static final String connectString = "zookeeper01:2181,zookeeper02:2181,zookeeper03:2181";
//超时时间
private static final int sessionTimeout = 2000;
//父节点
private static final String parentNode = "/locks";
//记录自己创建子节点的路径
private volatile String thisPath;
public static void main(String[] args) throws Exception {
//1.获取 ZooKeeper 的客户端连接
DistributedLock distLock = new DistributedLock();
distLock.getZKClient();
//2.注册一把锁
distLock.regiestLock();
//3.监听父节点,判断是否只有自己在线
distLock.watchParent();
}
2. main 方法中定义了三个方法
1)getZKClient():用来获取 Zookeeper 客户端的连接
其中 process 方法是当监听节点发生变化时调用,其中获取定义的父节点的所有子节点,然后判断当前节点是否是最小节点,若是则进行业务逻辑处理阶段,并重新注册一把新的锁
//获取 zk 客户端
public void getZKClient() throws Exception {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override
public void process(WatchedEvent event) {
//判断事件类型,只处理子节点变化事件
if(event.getType() == EventType.NodeChildrenChanged && event.getPath().equals(parentNode)) {
try {
List<String> childrens = zkClient.getChildren(parentNode, true);
//判断自己是否是最小的
String thisNode = thisPath.substring((parentNode + "/").length());
Collections.sort(childrens);
if(childrens.indexOf(thisNode) == 0){
//处理业务逻辑
dosomething();
//重新注册一把新的锁
thisPath = zkClient.create(parentNode + "/lock", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
2)main 中的第二个方法是 rediestLock()
调用 Zookeeper 客户端的 create() 方法,建立一个新的节点
//注册一把锁
public void regiestLock() throws Exception {
thisPath = zkClient.create(parentNode + "/lock", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
}
3)第三个是 watchParent() 方法
在此方法中判断是否只有一个节点在线,若只有自己一个节点,则调用业务处理的方法
//监听父节点,判断是否只有自己在线
public void watchParent() throws Exception {
List<String> childrens = zkClient.getChildren(parentNode, true);
if (childrens != null && childrens.size() == 1) {
//只有自己在线,处理业务逻辑(处理完业务逻辑,必须删释放锁)
dosomething();
} else {
//不是只有自己在线,说明别人已经获取到锁,等待
Thread.sleep(Long.MAX_VALUE);
}
}
4)最后一个是自定义的业务逻辑方法
需要注意的是,当处理完业务逻辑后,必须释放锁
//业务逻辑方法,注意:需要在最后释放锁
public void dosomething() throws Exception {
System.out.println("或得到锁:" + thisPath);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("释放锁:" + thisPath);
zkClient.delete(thisPath, -1);
}
}
3. 最后贴一下全部代码
package com.software.bigdata.zkdistlock; import java.util.Collections;
import java.util.List; import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper; /**
* @Description: 分布式共享锁
*
* @author Crawl
* @date 2018年1月25日 下午5:02:42
*/
public class DistributedLock { private ZooKeeper zkClient = null; //连接字符串
private static final String connectString = "zookeeper01:2181,zookeeper02:2181,zookeeper03:2181"; //超时时间
private static final int sessionTimeout = 2000; //父节点
private static final String parentNode = "/locks"; //记录自己创建子节点的路径
private volatile String thisPath; public static void main(String[] args) throws Exception {
//1.获取 ZooKeeper 的客户端连接
DistributedLock distLock = new DistributedLock();
distLock.getZKClient(); //2.注册一把锁
distLock.regiestLock(); //3.监听父节点,判断是否只有自己在线
distLock.watchParent();
} //业务逻辑方法,注意:需要在最后释放锁
public void dosomething() throws Exception {
System.out.println("或得到锁:" + thisPath);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("释放锁:" + thisPath);
zkClient.delete(thisPath, -1);
}
} //监听父节点,判断是否只有自己在线
public void watchParent() throws Exception {
List<String> childrens = zkClient.getChildren(parentNode, true);
if (childrens != null && childrens.size() == 1) {
//只有自己在线,处理业务逻辑(处理完业务逻辑,必须删释放锁)
dosomething();
} else {
//不是只有自己在线,说明别人已经获取到锁,等待
Thread.sleep(Long.MAX_VALUE);
}
} //注册一把锁
public void regiestLock() throws Exception {
thisPath = zkClient.create(parentNode + "/lock", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
} //获取 zk 客户端
public void getZKClient() throws Exception {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override
public void process(WatchedEvent event) {
//判断事件类型,只处理子节点变化事件
if(event.getType() == EventType.NodeChildrenChanged && event.getPath().equals(parentNode)) {
try {
List<String> childrens = zkClient.getChildren(parentNode, true);
//判断自己是否是最小的
String thisNode = thisPath.substring((parentNode + "/").length());
Collections.sort(childrens);
if(childrens.indexOf(thisNode) == 0){
//处理业务逻辑
dosomething();
//重新注册一把新的锁
thisPath = zkClient.create(parentNode + "/lock", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
} }
ZooKeeper 分布式共享锁的实现的更多相关文章
- Zookeeper使用实例——分布式共享锁
前一讲中我们知道,Zookeeper通过维护一个分布式目录数据结构,实现分布式协调服务.本文主要介绍利用Zookeeper有序目录的创建和删除,实现分布式共享锁. 举个例子,性能管理系统中,告警规则只 ...
- zookeeper编程入门系列之zookeeper实现分布式进程监控和分布式共享锁(图文详解)
本博文的主要内容有 一.zookeeper编程入门系列之利用zookeeper的临时节点的特性来监控程序是否还在运行 二.zookeeper编程入门系列之zookeeper实现分布式进程监控 三. ...
- Zookeeper概念学习系列之zookeeper实现分布式共享锁
首先假设有两个线程, 两个线程要同时到mysql中更新一条数据, 对数据库中的数据进行累加更新.由于在分布式环境下, 这两个线程可能存在于不同的机器上的不同jvm进程中, 所以这两个线程的关系就是垮主 ...
- 8.6.zookeeper应用案例_分布式共享锁的简单实现
1.分布式共享锁的简单实现 在分布式系统中如何对进程进行调度,假设在第一台机器上挂载了一个资源,然后这三个物理分布的进程都要竞争这个资源,但我们又不希望他们同时 进行访问,这时候我们就需要一个协调器, ...
- ZooKeeper 分布式锁实现
1 场景描述 在分布式应用, 往往存在多个进程提供同一服务. 这些进程有可能在相同的机器上, 也有可能分布在不同的机器上. 如果这些进程共享了一些资源, 可能就需要分布式锁来锁定对这些资源的访问. 2 ...
- zookeeper 分布式锁原理
zookeeper 分布式锁原理: 1 大家也许都很熟悉了多个线程或者多个进程间的共享锁的实现方式了,但是在分布式场景中我们会面临多个Server之间的锁的问题,实现的复杂度比较高.利用基于googl ...
- Hadoop Zookeeper 分布式服务框架
what is Zookeeper? 1,开源的分布式的,为分布式应用提供协调服务的Apache项目2,提供一个简单原语集合,以便于分布式应用可以在它之上构建更高层次的同步服务3,设计非常易于编程,它 ...
- Curator Zookeeper分布式锁
Curator Zookeeper分布式锁 pom.xml中添加如下配置 <!-- https://mvnrepository.com/artifact/org.apache.curator/c ...
- Zookeeper分布式集群搭建
实验条件:3台安装linux的机子,配置好Java环境. 步骤1:下载并分别解包到每台机子的/home/iHge2k目录下,附上下载地址:http://mirrors.cnnic.cn/apache/ ...
随机推荐
- qrc资源文件加载后,裸机环境下图片不显示
问题描述:在qt开发环境下,使用qss进行界面美化工作,里面包含许多图片资源.最后项目决定把这些图片资源和代码一起打包.然后就把图片资源和qss文件一起编入qrc文件中进行编译.在本机开发环境下是没有 ...
- css样式清零及常用类
css样式清零及常用类 @charset "utf-8"; /*CSS Reset*/ /*"微软雅黑","\5FAE\8F6F\96C5\9ED1& ...
- java多线程(一)-概述
最近这段在看java多线程编程方面的东西.所以特写了几篇文章,来总结和回顾一下自己所学习到的相关知识.因为水平有限,文章中总结不全面甚至理解错误的地方,欢迎读者指点批评. 我们平时所接触到的程序,都是 ...
- 带以太网的MicroPython开发板:TPYBoardv201建立云加法器实例
转载请注明文章来源,MicroPythonQQ技术交流群:157816561,公众号:MicroPython玩家汇 前面的一篇文档向大家介绍了v201的开发板作为客户端终端向TCPS上传数据的基本过程 ...
- Hibernate中关于HQL查询返回List<Object>数据的结果集问题
---恢复内容开始--- 开发中遇到的一个小问题,使用Hibernate中的HQL查询时,使用query.list()查询出来的是一个List<Object>结果集 原来代码: publi ...
- J2EE 项目 org.apache.jasper.JasperException: 解决方法
项目从一个电脑转移到另一台电脑总是有各种意外qaq~ 刚放假把从实验室的项目拷回自己的电脑回家继续coding,结果出了这个错误.... 各个地方都调试原来是Tomcat版本问题!!!我电脑上的是6. ...
- 【分块】BZOJ2821 作诗(Poetize)
2821: 作诗(Poetize) Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 3265 Solved: 951[Submit][Status][ ...
- 大话python面向对象
前言 师门中每逢成人礼就要下山历练一番,小掌门今年成人礼,下山也有一段时日.可恰逢年底,今年百姓收成都不是很好,各大店铺也很少招人,再加上学艺不精,小掌门无事可做就只能饿肚子了.后来小掌门饿的实在不行 ...
- Java实现网页抓取的一个Demo
这个小案例的话我是存放在我的github 上. 下面给出链接自己可以去看下,也可以直接下载源码.有具体的说明 <Java网页抓取>
- 用Vue开发一个实时性时间转换功能,看这篇文章就够了
前言 最近有一个说法,如果你看见某个网站的某个功能,你就大概能猜出背后的业务逻辑是怎么样的,以及你能动手开发一个一毛一样的功能,那么你的前端技能算是进阶中高级水平了.比如咱们今天要聊的这个话题:如何用 ...