原创播客,如需转载请注明出处。原文地址: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 分布式共享锁的实现的更多相关文章

  1. Zookeeper使用实例——分布式共享锁

    前一讲中我们知道,Zookeeper通过维护一个分布式目录数据结构,实现分布式协调服务.本文主要介绍利用Zookeeper有序目录的创建和删除,实现分布式共享锁. 举个例子,性能管理系统中,告警规则只 ...

  2. zookeeper编程入门系列之zookeeper实现分布式进程监控和分布式共享锁(图文详解)

    本博文的主要内容有 一.zookeeper编程入门系列之利用zookeeper的临时节点的特性来监控程序是否还在运行   二.zookeeper编程入门系列之zookeeper实现分布式进程监控 三. ...

  3. Zookeeper概念学习系列之zookeeper实现分布式共享锁

    首先假设有两个线程, 两个线程要同时到mysql中更新一条数据, 对数据库中的数据进行累加更新.由于在分布式环境下, 这两个线程可能存在于不同的机器上的不同jvm进程中, 所以这两个线程的关系就是垮主 ...

  4. 8.6.zookeeper应用案例_分布式共享锁的简单实现

    1.分布式共享锁的简单实现 在分布式系统中如何对进程进行调度,假设在第一台机器上挂载了一个资源,然后这三个物理分布的进程都要竞争这个资源,但我们又不希望他们同时 进行访问,这时候我们就需要一个协调器, ...

  5. ZooKeeper 分布式锁实现

    1 场景描述 在分布式应用, 往往存在多个进程提供同一服务. 这些进程有可能在相同的机器上, 也有可能分布在不同的机器上. 如果这些进程共享了一些资源, 可能就需要分布式锁来锁定对这些资源的访问. 2 ...

  6. zookeeper 分布式锁原理

    zookeeper 分布式锁原理: 1 大家也许都很熟悉了多个线程或者多个进程间的共享锁的实现方式了,但是在分布式场景中我们会面临多个Server之间的锁的问题,实现的复杂度比较高.利用基于googl ...

  7. Hadoop Zookeeper 分布式服务框架

    what is Zookeeper? 1,开源的分布式的,为分布式应用提供协调服务的Apache项目2,提供一个简单原语集合,以便于分布式应用可以在它之上构建更高层次的同步服务3,设计非常易于编程,它 ...

  8. Curator Zookeeper分布式锁

    Curator Zookeeper分布式锁 pom.xml中添加如下配置 <!-- https://mvnrepository.com/artifact/org.apache.curator/c ...

  9. Zookeeper分布式集群搭建

    实验条件:3台安装linux的机子,配置好Java环境. 步骤1:下载并分别解包到每台机子的/home/iHge2k目录下,附上下载地址:http://mirrors.cnnic.cn/apache/ ...

随机推荐

  1. 【quickhybrid】iOS端的项目实现

    前言 18年元旦三天内和朋友突击了下,勉强是将雏形做出来了,后续的API慢慢完善.(当然了,主力还是那个朋友,本人只是初涉iOS,勉强能看懂,修修改改而已) 大致内容如下: JSBridge核心交互部 ...

  2. lodash源码分析之NaN不是NaN

    暗恋之纯粹,在于不求结果,完全把自己锁闭在一个单向的关系里面. --梁文道<暗恋到偷窥> 本文为读 lodash 源码的第五篇,后续文章会更新到这个仓库中,欢迎 star:pocket-l ...

  3. java 学习(二)

    public class Scoure { public static void main(String args[]) { int score=90; if (score>=85 && ...

  4. 【自问自答】关于 Swift 的几个疑问

    感觉自己给自己释疑,也是一个极为有趣的过程.这次,我还新增了"猜想"一栏,来尝试回答一些暂时没有足够资料支撑的问题. Swift 版本是:4.0.3.不同版本的 Swift,可能无 ...

  5. SQL基础学习_06_集合运算和联结

    集合运算 1. 并集:UNION     例:     SELECT shohin_id, shohin_mei    FROM Shohin    UNION    SELECT shohin_id ...

  6. Hibernate学习笔记(1)---hibernate快速上手与准备工作

    持久层介绍 持久化:将内存中的数据保存在磁盘等存储设备中. 持久化对象:指已经存储在数据库护着磁盘的业务对象 经典的软件应用体系结构(三层结构) 在三层结构中,由于业务逻辑除了负责业务逻辑以外,还要负 ...

  7. c/c++ 贪吃蛇控制台版

    贪吃蛇控制台版(操作系统win7 64位:编译环境gcc, vs2017通过,其它环境未测试 不保证一定通过) 运行效果: #include <iomanip> #include < ...

  8. Java学习笔记26(Math类、Arrays类、BigInteger类、BigDecimal类)

    Math类:数学工具类,做一些数学计算,开方,对数,三角函数等 所有方法都是静态方法,不需要建立对象,直接用类名调用即可 示例: 这里写几个在日常开发中会用到的,比如三角函数之类的平时不会用到,了解即 ...

  9. Python进阶内容(三)--- reduce

    描述 functools.reduce() 函数会对参数序列中元素进行累积.函数将一个数据集合(列表,元组等)中的所有数据进行下列操作:用传给reduce中的函数 function(有两个参数)先对集 ...

  10. 【KMP模板】简单写个KMP~

    本来easy的KMP 却一直过不了洛谷的模板题... 仔细一看原来在输出next数组时打的回车而不是空格... 身败名裂... 话说有个sunday貌似一般状况下比KMP快呢...去看看2333 #i ...