文档章节

ZooKeeper.分布式锁

脑丨残
 脑丨残
发布于 2017/05/25 15:44
字数 688
阅读 56
收藏 2

#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

© 著作权归作者所有

共有 人打赏支持
上一篇: Mysql.lock
下一篇: JVM.jmp
脑丨残
粉丝 8
博文 60
码字总数 23267
作品 0
西安
私信 提问
分布式锁与实现(二)基于ZooKeeper实现

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

rechardchensir
10/08
0
0
大数据教程(3.3):zookeeper简介

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

em_aaron
07/28
0
0
ZooKeeper可以用来做什么(转)

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

easonjim
2017/09/05
0
0
分布式锁与实现(二)——基于ZooKeeper实现

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

刘祖鹏
05/08
0
0
分布式网站架构后续:zookeeper技术浅析

 Zookeeper是hadoop的一个子项目,虽然源自hadoop,但是我发现zookeeper脱离hadoop的范畴开发分布式框架的运用越来越多。今天我想谈谈zookeeper,本文不谈如何使用zookeeper,而是zookeeper...

蓝狐乐队
2014/04/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS配置Tomcat监听80端口,虚拟主机

Tomcat更改默认端口为80 更改的配置文件是: /usr/local/tomcat/conf/server.xml [root@test-a ~]# vim /usr/local/tomcat/conf/server.xml # 找到 Connector port="8080" protocol="HTTP/1......

野雪球
今天
5
0
《稻盛和夫经营学》读后感心得体会3180字范文

《稻盛和夫经营学》读后感心得体会3180字范文: 一代日本经营之圣稻盛和夫凭借刻苦勤奋的精神以及深植于佛教的商业道德准则,成为了“佛系”企业家的代表人物。在《稻盛和夫经营学》“领导人...

原创小博客
今天
3
0
java框架学习日志-5(常见的依赖注入)

依赖注入(dependency injection) 之前提到控制反转(Inversion of Control)也叫依赖注入,它们其实是一个东西,只是看的角度不同,这章详细说一下依赖注入。 依赖——指bean对象创建依赖于...

白话
今天
4
0
红外接收器驱动开发

背景:使用系统的红外遥控软件没有反应,然后以为自己接线错误,反复测试,结果烧坏了一个红外接收器,信号主板没有问题。所以自己开发了一个红外接收器的python驱动。接线参见https://my.os...

mbzhong
今天
2
0
ActiveMQ消息传送机制以及ACK机制详解

AcitveMQ是作为一种消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的手段来确保消息的分发是可靠的。 一. ActiveMQ消息传送机...

watermelon11
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部