文档章节

ZooKeeper.分布式锁

脑丨残
 脑丨残
发布于 2017/05/25 15:44
字数 688
阅读 53
收藏 2
点赞 0
评论 0

#ZooKeeper.分布式锁

  • 看了好多版本的分布式锁,大同小异,其中有几个自旋exists监听节点,觉得很笨,那就再造个轮子吧
  • 思路无非都是相同的,利用ZooKeeper强一致特性
  1. 进程并发在固定父节点下创建不同的临时节点
  2. 查看创建的子节点,排序,取第一个,等于自己的节点,算获取到锁,执行操作,其他监听第一个节点,进入等待
  3. 第一个节点变动,所有机器收到事件,唤醒线程,删除自己的节点,进入步骤1
  • CountDownLatch 比较简洁,但是还是lock更直白,更明确。

tips

  • 这个轮子仅仅是个toy,真正生产环境考虑更多,如释放锁失败异常各种情况
public class ZKLock implements Lock{
	
	private static Logger log = Logger.getLogger(ZKLock.class.getSimpleName());
	
	private ZooKeeper zookpeer; 
	private List<ACL> acl = ZooDefs.Ids.OPEN_ACL_UNSAFE;
	private static final String ROOT = "/lock";
	private byte[] b = new byte[]{1};
	private String lock;
	private ReentrantLock reenLock = new ReentrantLock();
	private Condition condition = reenLock.newCondition();
	//private CountDownLatch c;
	private int i;
	
	public ZKLock(String zookpeer,int i) {
		try {
			this.i = i;
			this.zookpeer = new ZooKeeper(zookpeer,3000,new Watcher(){
				
				@Override
				public void process(WatchedEvent event) {
					System.out.println("==启动回调==");
				}});
			
			init();
		} catch (IOException e) {
			
		}
	}
	
	@Override
	public boolean tryLock() {
		reenLock.lock();
		try {
			System.out.println("===================");
			System.out.println("开始抢锁 机器" + i);
			//c = new CountDownLatch(1);
			String myLock = zookpeer.create(getLockName(), b, acl, CreateMode.EPHEMERAL);
			this.lock = getFirstNode();
			
			if(myLock.equals(this.lock)) {
				//获取到锁
				System.out.println("我获得锁,我是 机器" + i + ":" + this.lock + " !!!!!!!!!!!!");
			}
			else {
				System.out.println("我没抢到锁  机器" + i);
			}
			
			reg(zookpeer);
			
			condition.await();
			//c.await();
			System.out.println("释放锁 机器:" + i);
			if(zookpeer.exists(myLock, false) != null) {
				zookpeer.delete(myLock, -1);
			}
		} catch (KeeperException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			reenLock.unlock();
		}
		return false;
	}

	//初始化锁目录
	public void init(){
		try {
			if(zookpeer.exists(ROOT, false) == null) {
				zookpeer.create(ROOT,b, acl, CreateMode.PERSISTENT);
			}
		} catch (KeeperException e) {
			log.log(Level.WARNING,"root already exist",e);
		} catch (InterruptedException e) {
			log.log(Level.SEVERE,"connection fail");
		}
	}
	
	public void reg(ZooKeeper zk) {
		try {
			zk.exists(lock, new M());
		} catch (KeeperException e) {
		} catch (InterruptedException e) {
		}
	}
	
	class M implements Watcher{
		
		@Override
		public void process(WatchedEvent event) {
			reenLock.lock();
			try {
				System.out.println("节点变更 机器i" + i);
				//c.countDown();
				condition.signal();
				reg(zookpeer);
			} finally{
				reenLock.unlock();
			}
		}
	}
	
	@Override
	public void lock() {
		while(true){
			tryLock();
		}
	}

	private String getFirstNode() throws KeeperException, InterruptedException {
		List<String> children = zookpeer.getChildren(ROOT, false);
		Collections.sort(children);
		System.out.println("当前节点:" + Arrays.toString(children.toArray()));
		return ROOT + "/" + children.get(0);
	}

	private String getLockName() {
		String name = UUID.randomUUID().toString();
		return ROOT + "/" + name.substring(0,name.indexOf("-"));
	}	
        .....
}

//3线程模拟争夺 手动删除节点,可看到重新争锁
public class LockWatch {

	public static void main(String[] args) throws Exception {
		ExecutorService p = Executors.newCachedThreadPool();
		for(int i = 0; i < 3; i ++) {
			p.submit(new T(i));
		}
	}
}
class T implements Runnable{
	
	private int i;
	
	public T(int i){
		this.i = i;
	}
	@Override
	public void run() {
		final ZKLock z = new ZKLock("127.0.0.1",i);
		z.lock();
	}
}
==启动回调==
==启动回调==
==启动回调==
===================
===================
===================
开始抢锁 机器2
开始抢锁 机器0
开始抢锁 机器1
当前节点:[a63a788c, c61a117b, decc9d68]
当前节点:[a63a788c, c61a117b, decc9d68]
我没抢到锁  机器1
当前节点:[a63a788c, c61a117b, decc9d68]
我没抢到锁  机器0
我获得锁,我是 机器2:/lock/a63a788c !!!!!!!!!!!!
节点变更 机器i2
节点变更 机器i1
节点变更 机器i0
释放锁 机器:1
释放锁 机器:0
释放锁 机器:2

© 著作权归作者所有

共有 人打赏支持
脑丨残
粉丝 8
博文 59
码字总数 23267
作品 0
西安
分布式锁与实现(二)——基于ZooKeeper实现

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配...

刘祖鹏 ⋅ 05/08 ⋅ 0

ZooKeeper分布式专题与Dubbo微服务入门

ZooKeeper分布式专题与Dubbo微服务入门 网盘地址:https://pan.baidu.com/s/1TN6BlftB2uvvyVR7IDmODQ 密码: e6zt 备用地址(腾讯微云):https://share.weiyun.com/5539X2S 密码:65b36i Zo...

人气王子333 ⋅ 04/17 ⋅ 0

ZooKeeper可以用来做什么(转)

在ZooKeeper的官网上有这么一句话:ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing grou......

easonjim ⋅ 2017/09/05 ⋅ 0

阿里大数据攻城师教你怎样理解ZooKeeper(六)

Zookeeper是什么 是一个针对大型分布式系统的可靠协调系统; 提供的功能包括:配置维护、名字服务、分布式同步、组服务等; 目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效...

JAVA丶学习 ⋅ 04/13 ⋅ 0

ZooKeeper的应用场景(转)

应用场景1 :统一命名服务 分布式应用中,通常需要一套完备的命令机制,既能产生唯一的标识,又方便人识别和记忆。 我们知道,每个ZNode都可以由其路径唯一标识,路径本身也比较简洁直观,另...

easonjim ⋅ 2017/09/05 ⋅ 0

ZooKeeper学习笔记三 ZooKeeper与Paxos

本文学习内容来自: 《从Paxos到ZooKeeper分布式一致性原理与实践》 电子工业出版社 Apache ZooKeeper是由Apache Hadoop的子项目发展而来,于2010年11月正式成为了Apache的顶级项目。ZooKeep...

xundh ⋅ 04/27 ⋅ 0

基于redis和zookeeper的分布式锁实现方式

先来说说什么是分布式锁,简单来说,分布式锁就是在分布式并发场景中,能够实现多节点的代码同步的一种机制。从实现角度来看,主要有两种方式:基于redis的方式和基于zookeeper的方式,下面分...

技术小能手 ⋅ 06/08 ⋅ 0

分布式线程安全(redis、zookeeper、数据库)

https://blog.csdn.net/u010963948/article/details/79006572 Q:一个业务服务器,一个数据库,操作:查询用户当前余额,扣除当前余额的3%作为手续费 synchronized lock db lock Q:两个业务服...

silyvin ⋅ 05/05 ⋅ 0

大数据开发之zookeeper简介

首先安装hadooper必须安装zookeeper。 zookeeper在hadoop生态圈中起的非常重要的作用,一句话就是ZooKeeper是分布式系统中的协调系统。 浅谈zookeeper:zookeeper是什么? ZooKeeper是一个分布...

大数据陈斌 ⋅ 05/21 ⋅ 0

linux下zookeeper的集群搭建

第一次写博客 写的不好不要骂┗|`O′|┛ 嗷~~ 首先说一下Zookeeper的概念: Zookeeper是一个分布式协调服务;就是为用户的分布式应用程序提供协调服务 A、zookeeper是为别的分布式程序服务的...

zhaobocan ⋅ 05/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

如何使用serverchan微信推送告警

之前实现推送告警信息到微信的方法有如下几种: 1、通过企业公众号实现----收费: 2、通过QQ邮箱,在微信平台上开启收到邮件进行提醒; 3、第三方告警平台API,一般也是收费的; 不过最近看文...

问题终结者 ⋅ 32分钟前 ⋅ 0

TCP的RPC

RPC就是远程方法调用(Remote Process Call ),包含了客户端和服务端,涉及了对象的序列化传输。 1.服务端启动,注册远程调用的类2.客户端发送请求信息包含类、方法、参数的一些信息、序列化传...

Cobbage ⋅ 53分钟前 ⋅ 0

IOS-UI UI初步代码布局添加事件

ISO开发界面,UI是必须学习的一部分,其实很早之前想学来了,一直没有沉下心来学习。看到IOS的代码风格和布局就别扭的不行,跟java代码和android布局比较显得不是那么方便,所以一直到现在。...

京一 ⋅ 今天 ⋅ 0

浅谈OpenDaylight的二次开发

OpenDaylight作为一款开源SDN网络控制器,依托于强大的社区支持以及功能特性,成为了目前主流的SDN网络控制器开发平台。在比较稳定的OpenDaylight Helium版本中,已经为开发者提供了大量的网...

wangxuwei ⋅ 今天 ⋅ 0

API 开发中可选择传递 token 接口遇到的一个坑

在做 API 开发时,不可避免会涉及到登录验证,我使用的是jwt-auth 在登录中会经常遇到一个token过期的问题,在config/jwt.php默认设置中,这个过期时间是一个小时,不过为了安全也可以设置更...

等月人 ⋅ 今天 ⋅ 0

Java NIO之文件处理

程序要操作本地操作系统的一个文件,可以分为以下三个部分: 对文件位置的操作 对文件的操作 对文件内容的操作 其中,对文件内容的操作在 Java NIO之Channel 中已经有了介绍,通过FileChann...

士别三日 ⋅ 今天 ⋅ 0

Maven的pom.xml配置文件详解

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.......

小海bug ⋅ 今天 ⋅ 0

解决httpclient超时设置不生效的问题

最近公司有项目需要通过http调用第三方服务,且第三方服务偶有超时,故需要设置一定的超时时间防止不响应的情况出现。 初始设置如下: [java] view plain copy //超时设置 RequestConfig re...

Mr_Tea伯奕 ⋅ 今天 ⋅ 0

过滤器Filter和拦截器HandlerInterceptor

过滤器 依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要...

hutaishi ⋅ 今天 ⋅ 0

Redis入门详解(转)

Redis入门详解 Redis简介 Redis安装 Redis配置 Redis数据类型 Redis功能 持久化 主从复制 事务支持 发布订阅 管道 虚拟内存 Redis性能 Redis部署 Redis应用场景 Redis总结 Redis简介: Redi...

xiaoyaoyoufang ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部