文档章节

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

© 著作权归作者所有

共有 人打赏支持
脑丨残
粉丝 8
博文 60
码字总数 23267
作品 0
西安
大数据教程(3.3):zookeeper简介

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

em_aaron
07/28
0
0
分布式锁与实现(二)基于ZooKeeper实现

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

rechardchensir
10/08
0
0
分布式锁与实现(二)——基于ZooKeeper实现

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

刘祖鹏
05/08
0
0
分布式设计与开发(三)------高一致性服务ZooKeeper

分布式环境中大多数服务是允许部分失败,也允许数据不一致,但有些最基础的服务是需要高可靠性,高一致性的,这些服务是其他分布式服务运转的基础,比如naming service、分布式lock等,这些分...

山哥
2012/03/19
0
0
ZooKeeper学习第一期---Zookeeper简单介绍

一、分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技术。那么什么是分布式协调技术?那么我来告诉大家,其实分布式协调技术 主要用来解决分布式环境当中多...

卯金刀GG
2017/10/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

sed命令

10月17日任务 9.4/9.5 sed 1.sed(上)(下) 1.sed 匹配功能 #sed -n ‘/root/’ p test.txt 将带有root的内容打印出来 同时支持 . * 还有 + 不过需要脱译,或者在前面选项加r。 支持{ } 支...

hhpuppy
34分钟前
1
0
day120-20181018-英语流利阅读-待学习

千禧一代注意了:一大波公司正向你的钱包袭来 Daniel 2018-10-18 1.今日导读 这几年,你有没有发现,不管是在微信公众号还是在抖音,有越来越多的商家和品牌开始玩起了网络用语和表情包,从卖...

飞鱼说编程
43分钟前
1
0
IOasd

能够使用FileUtils常用方法操作文件 字符流体系介绍 : 在 IO 开发中, 我们传输最频繁的数据为字符, 而以字节的方式来传输字符数据会使程序员丧失对数据内容的判断.因为程序员只认识字符, 不认...

码农屌丝
今天
0
0
创建第一个react项目

sudo npm i -g create-react-app@1.5.2 create-react-app react-app cd react-apprm -rf package-lock.jsonrm -rf node_modules #主要是为了避免报错npm installnpm start......

lilugirl
今天
3
0
在浏览器中进行深度学习:TensorFlow.js (八)生成对抗网络 (GAN)

Generative Adversarial Network 是深度学习中非常有趣的一种方法。GAN最早源自Ian Goodfellow的这篇论文。LeCun对GAN给出了极高的评价: “There are many interesting recent development...

naughty
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部