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实现分布式锁服务(Chubby)
在分布式系统中,如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰,来保证一致性,在这种情况下,便需要使用到分布式锁例如有N台服务器同时 ...
- [转载] zookeeper 分布式锁服务
转载自http://www.cnblogs.com/shanyou/archive/2012/09/22/2697818.html 分布式锁服务在大家的项目中或许用的不多,因为大家都把排他放在数据库那 ...
- zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...
- 基于Zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...
- Zookeeper系列四:Zookeeper实现分布式锁、Zookeeper实现配置中心
一.Zookeeper实现分布式锁 分布式锁主要用于在分布式环境中保证数据的一致性. 包括跨进程.跨机器.跨网络导致共享资源不一致的问题. 1. 分布式锁的实现思路 说明: 这种实现会有一个缺点,即当 ...
- 10分钟看懂!基于Zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...
- ZooKeeper示例 分布式锁
[转载请注明作者和原文链接, 如有谬误, 欢迎在评论中指正. ] 场景描述 在分布式应用, 往往存在多个进程提供同一服务. 这些进程有可能在相同的机器上, 也有可能分布在不同的机器上. 如果这些进程 ...
- 基于ZooKeeper实现——分布式锁与实现
引言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...
- java就业指南 zookeeper分布式系统 zookeeper实现分布式锁 有用
目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们“任何一个 分布式系统都无法同时满足一致性(Consistency).可用性 ...
随机推荐
- Openjudge-计算概论(A)-求平均年龄
描述: 班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄,保留到小数点后两位. 输入第一行有一个整数n(1<= n <= 100),表示学生的人数.其后n行每行有1个 ...
- php随意笔记
local(局部) global(全局)global 关键词用于访问函数内的全局变量.$GLOBALS[index] 的数组中存储了所有的全局变量.这个数组在函数内也可以访问,并能够用于直接更新全局变 ...
- NYOJ-915 +-字符串(贪心)
+-字符串 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 Shiva得到了两个只有加号和减号的字符串,字串长度相同.Shiva一次可以把一个加号和它相邻的减号交换. ...
- abstract和interface
1.abstract 的应用 abstract class ShapesClass { public abstract int Area(); } class Square : ShapesClass ...
- FTP、TFTP
FTP 文件传送协议 (File Transfer Protocol) FTP是因特网上使用得最广泛的文件传送协议. 文件传送协议 FTP (File Transfer Protocol) 是因 ...
- [VC++]用CTime类得到当前日期、时间、星期,格式化(详细讲解)
用CTime类得到当前日期.时间.星期,格式化(详细讲解)2009/05/12 09:48 A.M.① 定义一个CTime类对象 CTime time; ② 得到当前时间 time = CTime:: ...
- Chapter 2 Open Book——1
The next day was better… and worse. 明天会更好也会更坏. It was better because it wasn't raining yet, though t ...
- document.domain的修改问题
有时候,需要修改document.domain. 典型的情形:http://a.xxx.com/A.htm 的主页面有一个<iframe src="http://b.xxx.com/B ...
- C++ primer 练习 12.7
重做上一题,这次使用shared_ptr 而不是内置指针.上一题题目为:(编写函数,返回一个动态分配的int的vector.将此vector传递给另一个函数,这个函数读取标准输入,将读入的值保存在ve ...
- project文件问题
到编译文件中看看,红色的删除,坤哥这样做的 .