文中包含的几个部分的图片没法显示,能够到:http://note.youdao.com/share/?id=3651565d31662d82cd6e2d5abbd99749&type=note 查看全文,html
文中的各个部分都给出了引用连接,也能够直接查看node
一、分布式服务框架 Zookeeper -- 管理分布式环境中的数据web
二、简单的例子算法
三、ZooKeeper的实现机理数据库
四、ZooKeeper的应用领域http://blog.csdn.net/y_xianjun/article/details/8190500apache
五、ZooKeeper分布式锁
缓存
六、ZooKeeper一致性协议-Zab
安全
七、ZooKeeper选举和同步
服务器
一些有用的link:
http://www.cnblogs.com/mandela/archive/2011/08/09/2132122.html
http://blog.csdn.net/cnhzgb/article/details/7700026
一、分布式服务框架 Zookeeper -- 管理分布式环境中的数据
详细内容参见 link:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
分布式服务框架 Zookeeper -- 管理分布式环境中的数据
简介: Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中常常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。本文将从使用者角度详细介绍 Zookeeper 的安装和配置文件中各个配置项的意义,以及分析 Zookeeper 的典型的应用场景(配置文件的管理、集群管理、同步锁、Leader 选举、队列管理等),用 Java 实现它们并给出示例代码。
二、简单的例子:
link:http://www.oschina.net/p/zookeeper
假设咱们咱们有个20个搜索引擎的服务器(每一个负责总索引中的一部分的搜索任务)和一个 总服务器(负责向这20个搜索引擎的服务器发出搜索请求并合并结果集),一个备用的总服务器(负责当总服务器宕机时替换总服务器),一个web的 cgi(向总服务器发出搜索请求).搜索引擎的服务器中的15个服务器如今提供搜索服务,5个服务器正在生成索引.这20个搜索引擎的服务器常常要让正在 提供搜索服务的服务器中止提供服务开始生成索引,或生成索引的服务器已经把索引生成完成能够提供搜索服务了.使用Zookeeper能够保证总服务器自动 感知有多少提供搜索引擎的服务器并向这些服务器发出搜索请求,备用的总服务器宕机时自动启用备用的总服务器,web的cgi可以自动地获知总服务器的网络 地址变化.这些又如何作到呢?
- 提供搜索引擎的服务器都在Zookeeper中建立znode,zk.create("/search/nodes/node1",
"hostname".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateFlags.EPHEMERAL); - 总服务器能够从Zookeeper中获取一个znode的子节点的列表,zk.getChildren("/search/nodes", true);
- 总服务器遍历这些子节点,并获取子节点的数据生成提供搜索引擎的服务器列表.
- 当总服务器接收到子节点改变的事件信息,从新返回第二步.
- 总服务器在Zookeeper中建立节点,zk.create("/search/master", "hostname".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateFlags.EPHEMERAL);
- 备用的总服务器监控Zookeeper中的"/search/master"节点.当这个znode的节点数据改变时,把本身启动变成总服务器,并把本身的网络地址数据放进这个节点.
- web的cgi从Zookeeper中"/search/master"节点获取总服务器的网络地址数据并向其发送搜索请求.
- web的cgi监控Zookeeper中的"/search/master"节点,当这个znode的节点数据改变时,从这个节点获取总服务器的网络地址数据,并改变当前的总服务器的网络地址.
三、ZooKeeper的实现机理
link:http://bbs.zoomla.cn/archiver/showtopic-15086.aspx
ZooKeeper的实现机理是我看过的开源框架中最复杂的,它的解决是分布式环境中的一致性问题,这个场景也决定了其实现的复杂性。看了两三天的源码仍是有些摸不着头脑,有些超出了个人能力,不过经过看文档和其余高人写的文章大体清楚它的原理和基本结构。
1)ZooKeeper的基本原理
ZooKeeper是以Fast Paxos算法为基础的(不是zab?),在前一篇blog中大体介绍了一下paxos,而没有提到的是paxos存在活锁的问题,也就是当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos做了一些优化,经过选举产生一个leader,只有leader才能提交propose,具体算法可见Fast Paxos。所以,要想弄得ZooKeeper首先得对Fast Paxos有所了解。
2)ZooKeeper的基本运转流程
ZooKeeper主要存在如下两个流程:
选举Leader
同步数据
选举Leader过程当中算法有不少,但要达到的选举标准是一致的:
Leader要具备最高的zxid
集群中大多数的机器获得响应并follow选出的Leader
同步数据这个流程是ZooKeeper的精髓所在,而且就是Fast Paxos算法的具体实现。一个牛人画了一个ZooKeeper数据流动图,比较直观地描述了ZooKeeper是如何同步数据的。
以上两个核心流程我暂时还不能悟透其中的精髓,这也和我尚未彻底理解Fast Paxos算法有关,有待后续深刻学习
四、ZooKeeper的应用领域
Tim在blog中提到了Paxos所能应用的几个主要场景,包括database replication、naming service、config配置管理、access control list等等,这也是ZooKeeper能够应用的几个主要场景。此外,ZooKeeper官方文档中提到了几个更为基础的分布式应用,这也算是ZooKeeper的妙用吧
1)分布式Barrier
Barrier是一种控制和协调多个任务触发次序的机制,简单说来就是搞个闸门把欲执行的任务给拦住,等全部任务都处于能够执行的状态时,才放开闸门。它的机理能够见下图所示
:
在单机上JDK提供了CyclicBarrier这个类来实现这个机制,但在分布式环境中JDK就无能为力了。在分布式里实现Barrer须要高一致性作保障,所以ZooKeeper能够派上用场,所采取的方案就是用一个Node做为Barrer的实体,须要被Barrer的任务经过调用exists()检测这个Node的存在,当须要打开Barrier的时候,删掉这个Node,ZooKeeper的watch机制会通知到各个任务能够开始执行。
2)分布式Queue
与Barrier相似分布式环境中实现Queue也须要高一致性作保障,ZooKeeper提供了一个种简单的方式,ZooKeeper经过一个Node来维护Queue的实体,用其children来存储Queue的内容,而且ZooKeeper的create方法中提供了顺序递增的模式,会自动地在name后面加上一个递增的数字来插入新元素。能够用其children来构建一个queue的数据结构,offer的时候使用create,take的时候按照children的顺序删除第一个便可。ZooKeeper保障了各个server上数据是一致的,所以也就实现了一个分布式Queue。take和offer的实例代码以下所示
:
3)分布式lock
利用ZooKeeper实现分布式lock,主要是经过一个Node来表明一个Lock,当一个client去拿锁的时候,会在这个Node下建立一个自增序列的child,而后经过getChildren()方式来check建立的child是否是最靠前的,若是是则拿到锁,不然就调用exist()来check第二靠前的child,并加上watch来监视。当拿到锁的child执行完后归还锁,归还锁仅仅须要删除本身建立的child,这时watch机制会通知到全部没有拿到锁的client,这些child就会根据前面所讲的拿锁规则来竞争锁。
五、ZooKeeper分布式锁
(a)基于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地址写入节点数据中), 而后就能够返回一个锁了.
正确实现一个分布式锁是一件很是棘手的事情,由于很难对全部类型的故障进行正确的处理,ZooKeeper带有一个Java语言编写的生产级别的锁实现,名为WriteLock,客户端能够方便的使用它。
(b)zookeeper分布式锁
link:http://www.searchtb.com/2011/01/zookeeper-research.html
拥有了zookeeper如此强大的分布式协做系统后,咱们能够很容易的实现大量的分布式应用,包括了分布式锁,分布式队列,分布式Barrier,双阶段提交等等. 这些应用能够帮咱们改进不少复杂系统的协做方式,将这些系统的实现变得更加优雅而高效.鉴于篇幅,本文仅介绍分布式锁的实现.
利用了前文提到的sequence nodes能够很是容易的实现分布式锁. 实现分布式锁的基本步骤以下(这些步骤须要在全部须要锁的客户端执行):
- client调用create()建立名为”_locknode_/lock-”的节点,注意须要设置sequence和ephemeral属性
- client调用getChildren(“_locknode_”),注意不能设置watch,这样才能避免羊群效应
- 若是步骤1中建立的节点序号最低,则该client得到锁,开始执行其它程序
- client对lock-xxx中序号仅次于本身建立节点的那个节点调用exists(),并设置watch
- 若是exist()返回false(节点不存在)则回到步骤2,不然等待步骤4中的watch被触发并返回步骤2
分布式锁在zookeeper的源代码中已经有实现,能够参考org.apache.zookeeper.recipes.lock
六、ZooKeeper一致性协议-Zab
link:http://blog.csdn.net/chen77716/article/details/7309915
Zookeeper使用了一种称为Zab(Zookeeper Atomic Broadcast)的协议做为其一致性复制的核心,据其做者说这是一种新发算法,其特色是充分考虑了Yahoo的具体状况:高吞吐量、低延迟、健壮、简单,但不过度要求其扩展性。下面将展现一些该协议的核心内容:
另,本文仅讨论Zookeeper使用的一致性协议而非讨论其源码实现
Zookeeper的实现是有Client、Server构成,Server端提供了一个一致性复制、存储服务,Client端会提供一些具体的语义,好比分布式锁、选举算法、分布式互斥等。从存储内容来讲,Server端更多的是存储一些数据的状态,而非数据内容自己,所以Zookeeper能够做为一个小文件系统使用。数据状态的存储量相对不大,彻底能够所有加载到内存中,从而极大地消除了通讯延迟。
Server能够Crash后重启,考虑到容错性,Server必须“记住”以前的数据状态,所以数据须要持久化,但吞吐量很高时,磁盘的IO便成为系统瓶颈,其解决办法是使用缓存,把随机写变为连续写。
考虑到Zookeeper主要操做数据的状态,为了保证状态的一致性,Zookeeper提出了两个安全属性(Safety Property)
- 全序(Total order):若是消息a在消息b以前发送,则全部Server应该看到相同的结果
- 因果顺序(Causal order):若是消息a在消息b以前发生(a致使了b),并被一块儿发送,则a始终在b以前被执行。
- 由于只有一个Leader,Leader提交到Follower的请求必定会被接受(没有其余Leader干扰)
- 不须要全部的Follower都响应成功,只要一个多数派便可
2. Leader Election
- 老Leader在COMMIT前Crash(已经提交到本地)
- 老Leader在COMMIT后Crash,但有部分Follower接收到了Commit请求
3. Zab与Paxos
Because multiple leaders can propose a value for a given instance two problems arise. First, proposals can conflict. Paxos uses ballots to detect and resolve conflicting proposals. Second, it is not enough to know that a given instance number has been committed, processes must also be able to figure out which value has been committed.
- 以前的Phase2
- Learn
4.结束
- A simple totally ordered broadcast protocol
- paxos
七、ZooKeeper选举和同步
http://stblog.baidu-tech.com/?p=1164
用于分布式下一致性相关问题的解决方案。能够理解为由集群组成的可靠的单master。可将传统方案中的master使用zookeeper代替,且不用担忧单点问题。
应用场景:树状结构的命名服务、节点数据变动的消息通知、分布式共享锁、配置数据的集中存放、集群中节点机器的状态管理及状态变动通知
zookeeper实现分布式锁:经过zookeeper的节点状态进行条件判断,若是不知足,则在客户端本地加锁等待Object.wait()。利用zookeeper的实时通知机制,当zookeeper的节点知足条件状态时,客户端会同步得到通知,而后在本地解锁Object.notifyAll()。从而实现了分布式加锁、阻塞、解锁。
三类角色: leader(处理写请求,单点)、follower(处理客户端请求,参与投票)、observer(不投票,只处理客户端请求)
恢复模式:服务重启或者leader宕机后,经过paxos算法,从follower中从新选出leader,并以leader为准,进行数据同步。此时服务不可用。
paxos选举算法:
一、每次选举,都是针对某个txid(transaction id)进行。
二、每一个follower首先广播询问,获取其它全部server的txid、提议value,txid必须相同,value存储到提议列表中
三、follower从提议列表中获取value,若是这个value被大于一半的follower支持,则直接使用此value,不然,继续发出广播询问。而且将此value做为回答其它follower轮训的提议。
四、循环执行3,直到收敛
paxos的精髓:解决了集群中,非全联通状况下的一致性问题。对于正常全联通状况,每台机器只须要广播获取其它各台机器的数据,而后比较获取最大值便可。这样各个节点获得的结论应该是同样的。问题在于,某些节点之间是不联通的。因而某个节点没法获知全局数据,只能经过paxos中循环投票,收敛至全局最优解。
同步流程:选举完成后,各个follower向leader发送同步请求,带上本身的最大zxid。leader经过zxid肯定同步点,将这以后的commit log交给follower进行同步。全部节点都保存一份系统状态数据,非强一致(getData不保证最新数据,能够先sync一下保证数据的同步状态),有同步延时。
多节点可读可写,部分节点延时同步,最终一致性。follower和observer负责监听客户请求和处理读请求。对于全部写请求,都一概转发至leader进行选举和数据同步。observer不参与投票,只作数据同步,提升写请求的效率。