分布式之Zookeeper一(分布式锁与Zookeeper集群)
说到分布式开发,不得不说的就是zookeeper了;zookeeper官网说到Apache ZooKeeper致力于开发和维护可实现高度可靠的分布式协调的开源服务器。那么zk作为一个协调者的存在,是分布式比不可少的一部分。废话不多说,直接上干货
Zookeeper(https://zookeeper.apache.org/)的安装包可以直接在官网上获取,https://zookeeper.apache.org/doc/current/zookeeperStarted.html这里有Zookeeper的一些常用的简单命令,我们可以尝试着去试试它。
下面来说分布式锁,它用到的场景;比如:我们常说的惊群效应、Zookeeper集群争先读取缓存等。这里可能有人提到用redis实现的分布式锁,其实对比redis和Zookeeper的官网叙述,我们就能清晰的发现:Zookeeper比Redis更适合去做分布式锁。Zookeeper的担保第一条就是它的顺序性和一致性,其次是它的原子性。大家也可以详细的去了解一下。再分清楚这些之后,我们可以试着思考下Zookeeper它是怎么去实现的分布式锁?根据什么去实现的?
可以想到如何获取到Zookeeper的每个节点以及子节点变化,Zookeeper的Watch机制充分的实现了这一点。通过Watch机制可以清晰的监听到Zookeeper的每个节点的变化。自然而然的这里也要用到Zookeeper的第三方客户端。Zookeeper的第三方客户端有两个;一个是zkclient、一个是curator。在curator中它自己已经实现了分布式锁,感兴趣的可以去看看它的实现源码。
在第三方客户端连接到Zookeeper之后,就可以开始实现分布式锁了。锁的排他性、堵塞性、可重入性。排他性zk默认就实现了,zk的节点必须是唯一的。分布式锁采用Zookeeper的临时顺序节点来实现,首先获取锁,创建一个Zookeeper的临时顺序节点;然后需要一个栅栏(CountDownLatch),确保所有人都拿到自己的编号,即在同一起跑线上。然后开始抢锁,给一个发令枪(CountDown)。然后抢到锁的就去执行自己的业务,watch再次监听节点数据变化,然后请求线程去进行阻塞等待,接下来再删除节点,释放锁。
public boolean tryLock() {
if(currentPath.get() == null || !client.exists(currentPath.get())) {
String node = client.createEphemeralSequential(LockPath+"/", "locked");
currentPath.set(node);
}
List<String> children =client.getChildren(LockPath);
// 排序list
Collections.sort(children);
// 判断当前节点是否是最小的
if(currentPath.get().equals(LockPath+"/"+children.get(0))) {
return true;
}else {
int curIndex = children.indexOf(currentPath.get().substring(LockPath.length() + 1));
String bnode = LockPath+"/"+children.get(curIndex -1);
beforePath.set(bnode);
}
return false;
}
public void lock() {
if(! tryLock()) {
// 阻塞等待锁的释放
waitForLock();
// 重新抢锁
lock();
}
}
private void waitForLock() {
CountDownLatch cdl = new CountDownLatch(1);
// 用zkwatcher事件来通知
IZkDataListener listener = new IZkDataListener() {
public void handleDataDeleted(String dataPath) throws Exception {
System.out.println("================zk节点被删除================");
cdl.countDown();
}
public void handleDataChange(String dataPath, Object data) throws Exception {
}
};
// watcher /zk 数据变化
client.subscribeDataChanges(beforePath.get(), listener);
// 请求线程去进行阻塞等待
if(client.exists(beforePath.get())) {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 取消注册事件
client.unsubscribeDataChanges(beforePath.get(), listener);
}
至此一个分布式锁就实现了。
接下来说Zookeeper的伪集群。搭建的时候需要注意的情况:
1、DataDir的位置。
2、Zookeeper的端口号
3、

4、myid文件,myid文件是创建在DataDir目录下的,myid文件就是给一个id数,id数需与server.1 ... 后边的编号一致。
然后分别启动三台服务器,注意看服务器输出的日志消息。不出意外的话Zookeeper的集群就可以搭建成功了!
分布式之Zookeeper一(分布式锁与Zookeeper集群)的更多相关文章
- zookeeper的单实例和伪集群部署
原文链接: http://gudaoyufu.com/?p=1395 zookeeper工作方式 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现 ...
- Zookeeper笔记之使用zk实现集群选主
一.需求 在主从结构的集群中,我们假设硬件机器是很脆弱的,随时可能会宕机,当master挂掉之后需要从slave中选出一个节点作为新的master,使用zookeeper可以很简单的实现集群选主功能. ...
- ZooKeeper实践:(2)集群管理
前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...
- ZooKeeper实践:(1)集群管理
前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...
- zookeeper在windows下的伪集群模式
参考:zookeeper在windows下的伪集群模式 踩到的坑: 注意windows下路径需要使用\ dataDir=D:\Program Files\Java\zookeeper-3.4.10-c ...
- docker swarm英文文档学习-11-上锁你的集群来保护你的加密密钥
Lock your swarm to protect its encryption key上锁你的集群来保护你的加密密钥 在Docker 1.13及更高版本中,默认情况下,群管理器使用的Raft日志在 ...
- Zookeeper节点增删改查与集群搭建(笔记)
1.上传文件目录说明 上传的文件一般放在 /home/下 安装文件一般在 /usr/local/下 2. 安装zookeeper 2.1将zookeeper-3.4.11.tar.gz拷贝到/home ...
- (1)Zookeeper在linux环境中搭建集群
1.简介 ZooKeeper是Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务.同步服务和命名注册.ZooKeeper的架构通过冗余服务实现高可用性.Zookeeper ...
- 分布式Hbase-0.98.4在Hadoop-2.2.0集群上的部署
fesh个人实践,欢迎经验交流!本文Blog地址:http://www.cnblogs.com/fesh/p/3898991.html Hbase 是Apache Hadoop的数据库,能够对大数据提 ...
- Zookeeper 2、Zookeeper的安装和配置(集群模式)
1.下载与解压 Zookeeper下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper/ 下载完成以后解压到一个特定目录 同步时间所有节点的时间,并关 ...
随机推荐
- sql如何判断表字段是否存在默认值
if exists(SELECT 1 FROM sys.tables t INNER JOIN sys.columns c ON ...
- 深入理解MySQL索引原理和实现——为什么索引可以加速查询?
说到索引,很多人都知道“索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某 ...
- 「java.util.concurrent并发包」之 CountDownLatch
一 CountDownLatch是什么 CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier.Semaphore.ConcurrentHas ...
- 关于python中的包,模块导入的问题详解(二)
from import导入 紧接着的是from xx import xx 语法 1 ################ 2 from my_moudule import name 3 print(na ...
- Java中的自动拆装箱(转)
出处: 一文读懂什么是Java中的自动拆装箱 本文主要介绍Java中的自动拆箱与自动装箱的有关知识. 基本数据类型 基本类型,或者叫做内置类型,是Java中不同于类(Class)的特殊类型.它们是我 ...
- Open API
OAuth和SSO都可以做统一认证登录,但是OAuth的流程比SSO复杂.SSO只能做用户的认证登录,OAuth不仅能做用户的认证登录,开可以做open api开放更多的用户资源. Open API即 ...
- asp.net 5.图片和验证码
1.基本画图 //给用户创建一张图片,并且保持一张图片. //创建一个画布 , )) { //绘画布创建一个画笔 using (Graphics g = Graphics.FromImage(map) ...
- 【题解】JSOI2008 最大数
题目描述 现在请求你维护一个数列,要求提供以下两种操作: 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当前数列的长度.(L>=0) 插 ...
- HashMap工作原理总结
看了不少关于HaskMap工作原理的博客,下面自己总结记录一下: 1.了解HashMap之前,需要知道Object类的两个方法:hashCode和equals: 默认实现方法: /** JNI,调用底 ...
- 帝国cms 权限操作
<? if ($classid==5 || $classid==6 || $classid==7 || $classid==8 || $classid==9 || $classid==10 || ...