原创播客,如需转载请注明出处。原文地址: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. input选择框样式修改与自定义

    html自带的选择框样式不好看,并且在ios设备上丑的罚款.所以一般都是自定义样式: 原理:将原来默认的input选择框隐藏,然后控制label的:before与:after,配合矢量图标或者图片来实 ...

  2. Django__Ready

    Python WEB框架 : DJango : 大而全 flask : 小而精 tornado : 下载DJango : PIP3 INSTALL DJANGO 创建DJango项目 : django ...

  3. robotframework的学习笔记(十五)----robotframework标准库Collections

    Collections库是RobotFramework用来处理列表和字典的库,官方文档是这样介绍的:A test library providing keywords for handling lis ...

  4. [SharePoint]解决用户权限被无缘无故自动删除的问题

    前几天在维护公司内网的时候接到了一个case, 说是某个用户的权限无缘无故的就会被SharePoint自动去掉. 刚开始我还不愿意相信这个用户的说法,认为可能是权限赋的方法不对,有可能是被其他人误删了 ...

  5. bootstrap媒体查询

    Bootstrap 中的媒体查询允许您基于视口大小移动.显示并隐藏内容.下面的媒体查询在 LESS 文件中使用,用来创建 Bootstrap 网格系统中的关键的分界点阈值. /* 超小设备(手机,小于 ...

  6. IIS发布 用户 \'IIS APPPOOL\\X\' 登录失败

    曾多次遇到这个问题,我的解决方案就是修改数据库连接字符串 网上给的解决方案就是更换应用程序池的"进程模型":参考:http://jingyan.baidu.com/album/20 ...

  7. 登陆模块的进化史,带大家回顾java学习历程(一)

    一直在想着写点特别点的东西,让有兴趣学编程的人确实能学到点干货,今天就来随意写写. 大家在网上查找资料看到最多的demo估计就是登陆功能的演示了,为何大家偏爱拿登陆来做demo呢?因为行业应用类程序的 ...

  8. [整理]k-vim-for-server通过vimrc修改vim格式

    1.备份原来的vim设置: cp ~/.vimrc ~/.vimrc_bak 2. 下载配置到指定目录 法一: curl https://raw.githubusercontent.com/wklke ...

  9. VFS四大对象之三 struct dentry

    继上一篇文章介绍了inode结构体:继续介绍目录项dentry: http://www.cnblogs.com/linhaostudy/p/7427794.html 三.dentry结构体 目录项:目 ...

  10. vivi虚拟摄像头驱动程序

    一.vivi虚拟摄像头驱动 基于V4L2(video for linux 2)摄像头驱动程序,我们减去不需要的ioctl_fops的函数,只增加ioctl函数增加的必要的摄像头流查询等函数: #inc ...