基于zookeeper实现的分布式锁
基于zookeeper实现的分布式锁
A distributed lock base on zookeeper.
zookeeper是hadoop下面的一个子项目, 用来协调跟hadoop相关的一些分布式的框架, 如hadoop, hive, pig等, 其实他们都是动物, 所以叫zookeeper(本人歪歪).
zookeeper其实是集群中每个节点都维护着一棵相同的树, 树的结构跟linux的目录结构的概念差不多, 以/为跟节点, 下边可以扩展任意的节点和叶子节点, 每个节点都可以写入数据. 基于zookeeper的分布式锁的实现, 其实是得益于zookeeper同步文件的强大性, 我们相信每时每刻我们访问zookeeper的树时, 相同节点返回的数据都是一致的. 这要靠zookeeper内部的一些算法来实现. 特别是leader的选举算法, 这里就不说了, 感兴趣的话可以去搜索一下看看.
我们知道了zookeeper集群的每个节点的数据都是一致的, 那么我们可以通过这些节点来作为锁的标志.
首先给锁设置一下API, 至少要包含, lock(锁住), unlock(解锁), isLocked(是否锁住)三个方法
然后我们可以创建一个工厂(LockFactory), 用来专门生产锁.
锁的创建过程如下描述:
前提:每个锁都需要一个路径来指定(如:/jiacheo/lock)
1.根据指定的路径, 查找zookeeper集群下的这个节点是否存在.(说明已经有锁了)
2. 如果存在, 根据查询者的一些特征数据(如ip地址/hostname), 当前的锁是不是查询者的
3. 如果不是查询者的锁, 则返回null, 说明创建锁失败
4. 如果是查询者的锁, 则把这个锁返回给查询者
5. 如果这个节点不存在, 说明当前没有锁, 那么创建一个临时节点, 并将查询者的特征信息写入这个节点的数据中, 然后返回这个锁.
根据以上5部, 一个分布式的锁就可以创建了.
创建的锁有三种状态:
1. 创建失败(null), 说明该锁被其他查询者使用了.'
2. 创建成功, 但当前没有锁住(unlocked), 可以使用
3. 创建成功, 但当前已经锁住(locked)了, 不能继续加锁.

如图, 如果我们getLock("/jiacheo/lock1","192.168.0.100"), 想要获取/jiacheo/lock1这个锁的话, 我们先判断这个节点是否存在, 存在的话获取他的数据(data), 然后通过解析data, 我们可以知道这个节点是不是我们查询者创建的(通过ip地址写入节点数据中), 然后就可以返回一个锁了.
具体的java实现(implementation)代码如下:
1. Lock.java
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package org.jiacheo.zkdl.lock;import java.net.InetAddress;import java.net.UnknownHostException;import org.apache.zookeeper.KeeperException;import org.apache.zookeeper.ZooKeeper;import org.apache.zookeeper.data.Stat;/** * 类名:<b>Lock</b> <br/> * <p> * 类描述: * </p> * 创建人:jiacheo <br/> * 创建时间:2011-1-27 上午01:30:25 <br/> * @version 2011-1-27 * */public class Lock { private String path; private ZooKeeper zooKeeper; public Lock(String path){ this.path = path; } /** * <p> * 方法描述: 上锁 lock it * </p> * 创建人:jiacheo <br/> * 创建时间:2011-1-27 上午01:30:50 <br/> * @throws Exception */ public synchronized void lock() throws Exception{ Stat stat = zooKeeper.exists(path, true); String data = InetAddress.getLocalHost().getHostAddress()+":lock"; zooKeeper.setData(path, data.getBytes(), stat.getVersion()); } /** * <p> * 方法描述:开锁 unlock it * </p> * 创建人:jiacheo <br/> * 创建时间:2011-1-27 上午01:31:20 <br/> * @throws Exception */ public synchronized void unLock() throws Exception{ Stat stat = zooKeeper.exists(path, true); String data = InetAddress.getLocalHost().getHostAddress()+":unlock"; zooKeeper.setData(path, data.getBytes(), stat.getVersion()); } /** * <p> * 方法描述:是否锁住了, isLocked? * </p> * 创建人:jiacheo <br/> * 创建时间:2011-1-27 上午01:31:43 <br/> * @return */ public synchronized boolean isLock(){ try { Stat stat = zooKeeper.exists(path, true); String data = InetAddress.getLocalHost().getHostAddress()+":lock"; String nodeData = new String(zooKeeper.getData(path, true, stat)); if(data.equals(nodeData)){// lock = true; return true; } } catch (UnknownHostException e) { // ignore it } catch (KeeperException e) { //TODO use log system and throw a new exception } catch (InterruptedException e) { // TODO use log system and throw a new exception } return false; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public void setZooKeeper(ZooKeeper zooKeeper) { this.zooKeeper = zooKeeper; } } |
2.LockFactory.java
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
package org.jiacheo.zkdl.lock;import java.io.IOException;import java.net.InetAddress;import java.util.Collections;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.ZooKeeper;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.ZooDefs.Perms;import org.apache.zookeeper.data.ACL;import org.apache.zookeeper.data.Stat;public class LockFactory { public static final ZooKeeper DEFAULT_ZOOKEEPER = getDefaultZookeeper(); //data格式: ip:stat 如: 10.232.35.70:lock 10.232.35.70:unlock public static synchronized Lock getLock(String path,String ip) throws Exception{ if(DEFAULT_ZOOKEEPER != null){ Stat stat = null; try{ stat = DEFAULT_ZOOKEEPER.exists(path, true); }catch (Exception e) { // TODO: use log system and throw new exception } if(stat!=null){ byte[] data = DEFAULT_ZOOKEEPER.getData(path, null, stat); String dataStr = new String(data); String[] ipv = dataStr.split(":"); if(ip.equals(ipv[0])){ Lock lock = new Lock(path); lock.setZooKeeper(DEFAULT_ZOOKEEPER); return lock; } //is not your lock, return null else{ return null; } } //no lock created yet, you can get it else{ createZnode(path); Lock lock = new Lock(path); lock.setZooKeeper(DEFAULT_ZOOKEEPER); return lock; } } return null; } private static ZooKeeper getDefaultZookeeper() { try { ZooKeeper zooKeeper = new ZooKeeper("10.232.35.72", 10*1000, new Watcher(){ public void process(WatchedEvent event) { //节点的事件处理. you can do something when the node's data change// System.out.println("event " + event.getType() + " has happened!"); } }); return zooKeeper; } catch (IOException e) { e.printStackTrace(); } return null; } private static void createZnode(String path) throws Exception{ if(DEFAULT_ZOOKEEPER!=null){ InetAddress address = InetAddress.getLocalHost(); String data = address.getHostAddress()+":unlock"; DEFAULT_ZOOKEEPER.create(path, data.getBytes(),Collections.singletonList(new ACL(Perms.ALL,Ids.ANYONE_ID_UNSAFE)) , CreateMode.EPHEMERAL); } }} |
基于zookeeper实现的分布式锁的更多相关文章
- 基于Zookeeper实现多进程分布式锁
一.zookeeper简介及基本操作 Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化.当对目录节点监控状态打开时,一旦目录节点的状态发生变化,Watc ...
- 基于zookeeper实现高性能分布式锁
实现原理:利用zookeeper的持久性节点和Watcher机制 具体步骤: 1.创建持久性节点 zkLock 2.在此父节点下创建子节点列表,name按顺序定义 3.Java程序获取该节点下的所有顺 ...
- 基于zookeeper简单实现分布式锁
https://blog.csdn.net/desilting/article/details/41280869 这里利用zookeeper的EPHEMERAL_SEQUENTIAL类型节点及watc ...
- 基于Zookeeper实现的分布式互斥锁 - InterProcessMutex
Curator是ZooKeeper的一个客户端框架,其中封装了分布式互斥锁的实现,最为常用的是InterProcessMutex,本文将对其进行代码剖析 简介 InterProcessMutex基于Z ...
- 基于数据库、redis和zookeeper实现的分布式锁
基于数据库 基于数据库(MySQL)的方案,一般分为3类:基于表记录.乐观锁和悲观锁 基于表记录 用表主键或表字段加唯一性索引便可实现,如下: CREATE TABLE `database_lock` ...
- java使用zookeeper实现的分布式锁示例
java使用zookeeper实现的分布式锁示例 作者: 字体:[增加 减小] 类型:转载 时间:2014-05-07我要评论 这篇文章主要介绍了java使用zookeeper实现的分布式锁示例,需要 ...
- 基于redis实现的分布式锁
基于redis实现的分布式锁 我们知道,在多线程环境中,锁是实现共享资源互斥访问的重要机制,以保证任何时刻只有一个线程在访问共享资源.锁的基本原理是:用一个状态值表示锁,对锁的占用和释放通过状态值来标 ...
- 如何用Zookeeper来实现分布式锁?
什么是Zookeeper临时顺序节点? 例如 : / 动物 植物 猫 仓鼠 荷花 松树 Zookeeper的数据存储结构就像一棵树,这棵树由节点组成,这种节点叫做Zonde.# Znode分为四种类型 ...
- ZooKeeper 笔记(6) 分布式锁
目前分布式锁,比较成熟.主流的方案有基于redis及基于zookeeper的二种方案. 大体来讲,基于redis的分布式锁核心指令为SETNX,即如果目标key存在,写入缓存失败返回0,反之如果目标k ...
随机推荐
- Vue官方文档中的camelCased (驼峰式) 命名与 kebab-case
因为html特性中 元素的 prop是不区分大小写的 所以不管html中怎么大写小写变化,下面的组件的prop应该写成小写 Vue中有这样一种设定: props中如果使用为kebab-case命名方式 ...
- 学习《TensorFlow实战Google深度学习框架 (第2版) 》中文PDF和代码
TensorFlow是谷歌2015年开源的主流深度学习框架,目前已得到广泛应用.<TensorFlow:实战Google深度学习框架(第2版)>为TensorFlow入门参考书,帮助快速. ...
- 安装php-ldap模块
php-ldap模块作用就是实现ldap认证,因此需要安装 1.安装软件包解决依赖 yum install openldapyum install openldap-devel 2.拷贝库文件 cp ...
- 【Uva 10934】Dropping water balloons
[Link]: [Description] 等价题意: 某人在1..n内选一个数x; 然后让你去猜; 你可以问他是不是在哪个范围里; 每次会告诉你YES或者NO; 问你在最坏的情况下猜出答案需要猜多少 ...
- 如何形象的解释 webhook 这个词
就是一个 callback,只不过 callback 的操作是发送指定的 HTTP request 给一个指定的地址. callback 就是由甲传给乙,乙处理完之后通知甲传过来的方法或者请求甲方的 ...
- LinkedIn微服务框架rest.li
linkedin/rest.li https://github.com/linkedin/rest.li LinkedIn微服务框架rest.li摘要:Rest.li是一款REST+JSON框架,使 ...
- ubuntu系统配置WinQQ
首先安装Wine sudo add-apt-repository ppa:wine/wine-builds sudo apt-get update sudo apt-get install wineh ...
- 源码安装 ipython
https://blog.csdn.net/huobanjishijian/article/details/51470898
- 解决Docker容器内访问宿主机MySQL数据库服务器的问题
懒得描述太多,总归是解决了问题,方法简要记录如下,虽然简要,但是完整,一来纪念处理该问题耗费的大半天时间,二来本着共享精神帮助其他遇到该问题的哥们儿,当然这个方法并不一定能解决你们的问题,但是多少能提 ...
- 【hdu 4289】Control
[Link]:http://acm.hdu.edu.cn/showproblem.php?pid=4289 [Description] 给出一个又n个点,m条边组成的无向图.给出两个点s,t.对于图中 ...