说到分布式开发,不得不说的就是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集群)的更多相关文章

  1. zookeeper的单实例和伪集群部署

    原文链接: http://gudaoyufu.com/?p=1395 zookeeper工作方式 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现 ...

  2. Zookeeper笔记之使用zk实现集群选主

    一.需求 在主从结构的集群中,我们假设硬件机器是很脆弱的,随时可能会宕机,当master挂掉之后需要从slave中选出一个节点作为新的master,使用zookeeper可以很简单的实现集群选主功能. ...

  3. ZooKeeper实践:(2)集群管理

    前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...

  4. ZooKeeper实践:(1)集群管理

    前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...

  5. zookeeper在windows下的伪集群模式

    参考:zookeeper在windows下的伪集群模式 踩到的坑: 注意windows下路径需要使用\ dataDir=D:\Program Files\Java\zookeeper-3.4.10-c ...

  6. docker swarm英文文档学习-11-上锁你的集群来保护你的加密密钥

    Lock your swarm to protect its encryption key上锁你的集群来保护你的加密密钥 在Docker 1.13及更高版本中,默认情况下,群管理器使用的Raft日志在 ...

  7. Zookeeper节点增删改查与集群搭建(笔记)

    1.上传文件目录说明 上传的文件一般放在 /home/下 安装文件一般在 /usr/local/下 2. 安装zookeeper 2.1将zookeeper-3.4.11.tar.gz拷贝到/home ...

  8. (1)Zookeeper在linux环境中搭建集群

    1.简介 ZooKeeper是Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务.同步服务和命名注册.ZooKeeper的架构通过冗余服务实现高可用性.Zookeeper ...

  9. 分布式Hbase-0.98.4在Hadoop-2.2.0集群上的部署

    fesh个人实践,欢迎经验交流!本文Blog地址:http://www.cnblogs.com/fesh/p/3898991.html Hbase 是Apache Hadoop的数据库,能够对大数据提 ...

  10. Zookeeper 2、Zookeeper的安装和配置(集群模式)

    1.下载与解压 Zookeeper下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper/ 下载完成以后解压到一个特定目录 同步时间所有节点的时间,并关 ...

随机推荐

  1. swagger-注解

    常用注解 @Api(value = "xxx"):用于类,表示标识这个类是swagger的资源. tags–表示说明,如果有多个值,会生成多个list value–也是说明,可以使 ...

  2. RocketMQ之八:水平扩展及负载均衡详解

    RocketMQ是一个分布式具有高度可扩展性的消息中间件.本文旨在探索在broker端,生产端,以及消费端是如何做到横向扩展以及负载均衡的. NameServer集群 提供轻量级的服务发现和路由.每个 ...

  3. 生命周期中mounted和created的区别。

    一.什么是生命周期? 用通俗的语言来说,就是Vue中实例或者组件从创建到消灭中间经过的一系列过程.虽然不太严谨,但是也基本上可以理解. 通过一系列实践,现在把所有遇到的问题整理一遍,今天记录一下cre ...

  4. 写linux脚本你怎么能不知道位置参数!?

    在写shell脚本的时候,我们经常会手动设置参数,然后对我们的输入的这些参数进行处理和分析,那么这个东东到底值怎么使用的呢? 1.$n $0代表命令本身,$1-9代表接受的第1-9个参数,10以上需要 ...

  5. docker部署jar、war包方法

    一.将war包放入容器 1.# docker imagesREPOSITORY                         TAG                 IMAGE ID         ...

  6. Cookie中的httponly的属性和作用

    1.什么是HttpOnly? 如果cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击,窃取cookie内容,这样就增加了cookie的安 ...

  7. day22 subprocess、configeparser、表格操作模块

    今日内容: 1.configparser模块的使用 2.subprocess模块的使用 3.表格处理模块 xlrd模块 xlwt模块 1.configparser模块 configparser模块是用 ...

  8. day16 模块导入及环境变量

    """ 今日内容: 1.模块 2.模块的导入 3.环境变量sys.path 4.模块间的相互调用 """ """ ...

  9. 什么是JWT(Json Web Token)

    什么是 JWT (Json Web Token) 用户认证是计算机安全领域一个永恒的热点话题. JWT 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该to ...

  10. PAT(Advanced Level)1055.The World's Richest

    Forbes magazine publishes every year its list of billionaires based on the annual ranking of the wor ...