1、前述

上篇文章《hadoop系列:zookeeper(1)——zookeeper单点和集群安装》(http://blog.csdn.net/yinwenjie/article/details/47361419)我们介绍了zookeeper的两种安装方式。相信您的測试机或者VM上面已经有了一个可用的zookeeper环境了。

本文是zookeeper解说的第二篇文章。我们主要介绍zk中的重要基本原理。为后文给大家解说zk的java api使用打下基础。

不管您在工作中实际的角色是什么。假设您准备在实际工作中使用zookeeper技术,那么这篇文章介绍的基本原理您都应该了解。

2、zk的数据组织方式

首先我们在您的zk环境上使用zkCli.sh连接上去:

[root@vm2 ~]# zkCli.sh
Connecting to localhost:2181
2015-08-12 23:43:53,624 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.6-1569965, built on 02/20/2014 09:09 GMT
2015-08-12 23:43:53,639 [myid:] - INFO [main:Environment@100] - Client environment:host.name=vm2
2015-08-12 23:43:53,639 [myid:] - INFO [main:Environment@100] - Client environment:java.version=1.7.0_71
2015-08-12 23:43:53,642 [myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
。。 。。。 。
。。 。。 。。
。。。。。 。
。 。。。。。
[zk: localhost:2181(CONNECTED) 0]

然后我们使用ls命令,查看zookeeperserver上的数据存储信息:

[zk: localhost:2181(CONNECTED) 1] ls /
[filesq, zookeeper]

当然您还能够使用非常多命令,例如以下:

connect host:port
get path [watch]
ls path [watch]
set path data [version]
rmr path
delquota [-n|-b] path
quit
printwatches on|off
create [-s] [-e] path data acl
stat path [watch]
close
ls2 path [watch]
history
listquota path
setAcl path acl
getAcl path
sync path
redo cmdno
addauth scheme auth
delete path [version]
setquota -n|-b val path

假设您对以上命令感兴趣,能够查询zookeeper的官方文档去了解。

本文的内容我们将从ls命令得到的zookeeper中的数据结构讲开。

2.1、znode

依据本小结第一部分的描写叙述,非常显然zookeeper集群自身维护了一套数据结构。

这个存储结构是一个树形结构。其上的每个节点,我们称之为“znode”。

例如以下如所看到的:

  • 每个znode默认能够存储1MB的数据(对于记录状态性质的数据来说。够了)

  • 能够使用zkCli命令。登录到zookeeper上。并通过ls、create、delete、sync等命令操作这些znode节点

  • znode除了名称、数据以外,另一套属性:zxid。这套zid与时间戳相应,记录zid不同的状态(兴许我们将用到)

那么每个znode结构又是什么样的呢?例如以下图所看到的:

此外,znode还有操作权限。假设我们把以上几类属性细化。又能够得到下面属性的细节:

  • czxid:创建节点的事务的zxid
  • mzxid:对znode近期改动的zxid
  • ctime:以距离时间原点(epoch)的毫秒数表示的znode创建时间
  • mtime:以距离时间原点(epoch)的毫秒数表示的znode近期改动时间
  • version:znode数据的改动次数
  • cversion:znode子节点改动次数
  • aversion:znode的ACL改动次数
  • ephemeralOwner:假设znode是暂时节点。则指示节点全部者的会话ID;假设不是暂时节点。则为零。
  • dataLength:znode数据长度。
  • numChildren:znode子节点个数。

2.2、znode中的存在类型

我们知道了zookeeper内部维护了一套数据结构:由znode构成的集合。znode的集合又是一个树形结构。每个znode又有非常多属性进行描写叙述。而且znode的存在性还分为四类,例如以下如所看到的:

znode是由client创建的。它和创建它的client的内在联系,决定了它的存在性:

  • PERSISTENT-持久化节点:创建这个节点的client在与zookeeper服务的连接断开后,这个节点也不会被删除(除非您使用API强制删除)。

  • PERSISTENT_SEQUENTIAL-持久化顺序编号节点:当client请求创建这个节点A后,zookeeper会依据parent-znode的zxid状态。为这个A节点编写一个全文件夹唯一的编号(这个编号仅仅会一直增长)。当client与zookeeper服务的连接断开后。这个节点也不会被删除。

  • EPHEMERAL-暂时文件夹节点:创建这个节点的client在与zookeeper服务的连接断开后,这个节点(还有涉及到的子节点)就会被删除。

  • EPHEMERAL_SEQUENTIAL-暂时顺序编号文件夹节点:当client请求创建这个节点A后。zookeeper会依据parent-znode的zxid状态,为这个A节点编写一个全文件夹唯一的编号(这个编号仅仅会一直增长)。当创建这个节点的client与zookeeper服务的连接断开后,这个节点被删除。

  • 另外,不管是EPHEMERAL还是EPHEMERAL_SEQUENTIAL节点类型,在zookeeper的client异常终止后,节点也会被删除

3、zk中的选举FastLeaderELection

在上篇文章中,我们已经知道了一个zookeeper集群中。有一个处于leader身份的节点,其他的节点都是flower状态。

那么一个leader是怎么产生的呢?这就是zookeeper中的选举规则,默认的选举规则称为:FastLeaderELection(网上的资料还有提到另外的选举算法,实际上它们的核心思想都是一样的)

3.1、选举算法的中心思想

网上的资料有使用纯文字进行算法描写叙述的,也有使用流程图进行算法描写叙述的,可是假设读者不细致看,还是easy昏头转向,这里我们使用一张过程图和文字相结合的方式对FastLeaderELection选举算法进行描写叙述。

实际上FastLeaderELection说的中心思想无外乎下面几个关键点:

  • 全天下我最牛,在我没有发现比我牛的推荐人的情况下,我就一直推举我当leader。第一次投票那必须推举我自己当leader。

  • 每当我接收到其他的被推举者。我都要回馈一个信息。表明我还是不是推举我自己。

    假设被推举者没我大,我就一直推举我当leader,是我是我还是我!

  • 我有一个票箱, 和我属于同一轮的投票情况都在这个票箱里面。一人一票 反复的或者过期的票,我都不接受。

  • 一旦我不再推举我自己了(这时我发现别人推举的人比我推荐的更牛),我就把我的票箱清空。又一次发起一轮投票(这时我的票箱一定有两票了。都是选的我觉得最牛的人)。

  • 一旦我发现收到的推举信息中投票轮要高于我的投票轮,我也要清空我的票箱。而且还是投当初我觉得最牛的那个人(除非当前的人比我最初的推荐牛,我就顺带更新我的推荐)。

  • 不断的反复上面的过程,不断的告诉别人“我的投票是第几轮”、“我推举的人是谁”。直到我的票箱中“我推举的最牛的人”收到了不少于 N /2 + 1的推举投票。

  • 这时我就能够决定我是flower还是leader了(假设至始至终都是我最牛,那我就是leader咯。其他情况就是follower咯)。而且不论随后收到谁的投票,都向它直接反馈“我的结果”。

3.2、一张理想的图

那么我们依照以上的原则,进行一次投票。这是一个比較理想的状态,我们不考虑当中的网络延迟,不考虑启动zookeeper节点时本身的时间差,我们假设发出包的先后顺序,就是目标节点接受这些包的先后顺序。这个理想的过程中,我们同一时候开启5个zookeeper节点,让他们进行选举:

  • 在第一轮中,依照“我最牛逼,我怕谁”的原则,每个节点都推荐它自己为集群的leader节点。

  • 依照我们假设的理想条件,节点S1首先收到了S2发送来的推荐者“2”。节点S1发现“2”要比它之前推荐的“1”(也就是它自己)牛。依据谁牛推荐谁的原则,“S1”清空自己的票箱,又一次选举“2”(注意。此时“S1”的新票箱中已经有两票选举“2”了。一票是它自己,另外一票是”S2”,而且全部节点都是Looking状态)

  • 相同的事情发生在“S2”身上:”S2”收到了”S3”发过来的推荐信息,发现“3”这个被推举者比之前自己推举的“2”要牛,于是也清空自己的票箱,发起一轮新的投票,此时“S2”选举“3”。

    依次类推”S3”、”S4”。

  • 这里要注意S5这个节点,在第一轮接受到了来源于“S1”——“S4”的推举者(一定注意,每一次接受信息,都会广播一次“我坚持推举的人”),发现“还是推荐的5最牛”。于是“我继续推举S5吧”。

  • 以上这个过程在整个理想的网络环境上一直持续。

    到了第四轮,“S1”收到了“S2”发送来的推举者“5”,发现“5”要比当前“S1”推荐的“4”要牛。

    所以“S1”清空了自己的票箱。又一次推举“5”(发送给其他全部节点)

  • 关键的第五轮来了,我们再反复一下。经过之前的选举,如今“S2”——“S5”都已经推举“5”为Leader了,而且都处于第四轮。这时他们收到了”S1”发来的新的“第五轮”投票,于是都和之前一样,做相同的一件事:清空自己的票箱,又一次向其他全部节点广播自己的第五轮投票“5”。

  • 于是,节点X,收到了大于N / 2 +1的选举“5”的投票。且都是第五轮投票。这样每个节点就都知道了自己的角色。。选举结束。全部将成为Follower状态的节点,向将要成为Leader的节点发起最后一次“工作是否正常”的询问。得到肯定的ack后。整个集群的工作状态就确认了

3.3、实际上没有那么理想

关于上节的算法或者关于上上节的白话描写叙述,假设您一边没有看懂。请多看几遍。假设您看晕了,请歇息一下,清空脑袋。再看。选举算法的整个流程第一次是不好理解,可是一旦理解了当中的关键点,它就变得非常easy

我们在上文中介绍的选举流程是基于一个主要的考虑:理想的网络环节,理想的节点处理能力。但其实。没有这种环境。网络情况的多变导致了我们须要让选举算法兼容各种的情况。

下面我们假设在选举的过程中,“S1”,“S2”两个节点出现了宕机的情况(或者是网络延迟,或者是网络物理层断开,不管您怎么想吧,反正其他节点再也收到”S1”,”S2”的投票信息了)。例如以下图所看到的:

上图所看到的。在第三轮的选举过程后,“S1”,“S2”两个节点就断开了,他们的投票信息根本没有发送出去。

  • 这样一来。“S3”收到了“S4”,“S5”发来的投票信息。这时“S3”的票箱处于第3轮,而且发现了占大多数的投票结果:大家选举“S5”为Leader节点。

  • 相同的事情也发生在“S4”身上。

    这样“S3”,“S4”两个节点领先知道了投票结果,在最后一次询问Leader节点能否正常工作,并得到了肯定的ACK之后,“S3”,“S4”两个节点变成了Follower状态。

    • 之后,不管“S3”,“S4”两个节点收到了不论什么节点的投票信息,都直接向源节点反馈投票结果,不会再进行投票了。
  • 这样一来,在投票完毕后,“S1”,“S2”又一次连入后,尽管他们发起了投票,可是不会再收到投票反馈了

    直接依据“S3”或者“S4”发来的结果状态。变成Follower状态。

3.4、网上的资料

上图是网络上的一张选举过程图。步骤是怎么样的,笔者我就不再多说了,仅仅希望这个能辅助大家更好的理解选举过程。

哦,如今您知道为什么zookeeper在少于 N / 2 + 1的节点处于工作状态的情况下会崩溃了吧。由于。不管怎么选也没有不论什么节点能够获得 N / 2 + 1 的票数

4、后文介绍

本来,我是希望这篇文章向大家说明包含zookeeper选举原理和zookeeper中的事件监听watcher原理在内的两个核心原理。

奈何。内容量已经超出了我的想象。这种话同一时候介绍两种原理不利于大家对知识点的吸收消化。

所以我决定zookeeper事件监听的watcher原理,在下一篇文章中再具体介绍,当然会包含演示样例代码。

敬请期待。

hadoop系列:zookeeper(2)——zookeeper核心原理(选举)的更多相关文章

  1. Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

    一.高可用简介 Hadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求 ...

  2. ZooKeeper系列(一)—— ZooKeeper 简介及核心概念

    一.Zookeeper简介 Zookeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护.Zookeeper 可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调 ...

  3. zookeeper核心原理全面解析

    下述各zookeeper机制的java客户端实践参考zookeeper java客户端之curator详解. 官方文档http://zookeeper.apache.org/doc/current/z ...

  4. ZooKeeper系列(7):ZooKeeper一致性原理

    一.ZooKeeper 的实现 1.1 ZooKeeper处理单点故障 我们知道可以通过ZooKeeper对分布式系统进行Master选举,来解决分布式系统的单点故障,如图所示. 图 1.1 ZooK ...

  5. Zookeeper核心原理

    Zookeeper 的核心原理 Zookeeper 的由来 各个节点的数据一致性 怎么保证任务只在一个节点执行 如果orderserver1挂了,其他节点如何发现并接替 存在共享资源,互斥性.安全性 ...

  6. 深入了解Zookeeper核心原理

    之前的文章Zookeeper基础原理&应用场景详解中将Zookeeper的基本原理及其应用场景做了一个详细的介绍,虽然介绍了其底层的存储原理.如何使用Zookeeper来实现分布式锁.但是我认 ...

  7. Zookeeper概论(对zookeeper的概论、原理、架构等的理解)

    Zookeeper概论(对zookeeper的概论.原理.架构等的理解) 一.概论 Zookeeper是一个分布式的.开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是h ...

  8. zookeeper基本概念及原理

    zookeeper是一个分布式的,开源的分布式应用程序,该程序主要用于管理其他分布式应用程序.其他分布式应用程序可以基于zookeeper实现数据同步,配置维护和命名服务等等.zookeeper是Ha ...

  9. ZooKeeper学习之路(一)—— ZooKeeper简介及核心概念

    一.Zookeeper简介 Zookeeper是一个开源的分布式协调服务,目前由Apache进行维护.Zookeeper可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调/通知. ...

随机推荐

  1. Android-自己定义标题栏

    Android-自己定义标题栏 2014年4月25日 分享知识点 最近也比較多事情,想发发博客就是心有余而力不足,本篇博文主要教大家怎样实现自己定义标题栏,非常easy.那么聪明的你一下就看懂. 有兴 ...

  2. CF 558C(Amr and Chemistry-构造法)

    C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input standard ...

  3. Swift - 使用CollectionView实现图片Gallery画廊效果(左右滑动浏览图片)

    1,效果图 (1)图片从左至右横向排列(只有一行),通过手指拖动可以前后浏览图片. (2)视图滚动时,每张图片根据其与屏幕中心距离的不同,显示尺寸也会相应地变化.越靠近屏幕中心尺寸就越大,远离屏幕中心 ...

  4. hdoj--2120--Ice_cream's world I(并查集判断环)

    Ice_cream's world I Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  5. 对python变量的理解

    #!/usr/bin/python class Person: '''some words content or descriptions!''' name='luomingchuan' _age = ...

  6. Unity 默认进入的scenes

    1,如果有多个场景,那么第一个场景要放在最上边,(其他的也要加) 2,如果不添加,那么Unity会把当前打开的场景添加进来. 3,切换场景的代码 using UnityEngine.SceneMana ...

  7. Spring Batch 高级-

    spring batch / 并行处理 / 多线程 分区 1. 并行处理,多线程,分区 http://blog.csdn.net/github_36849773/article/details/692 ...

  8. JS判断客户端是否是iOS或者Android或者ipad(一)

    通过判断浏览器的userAgent,用正则来判断是否是ios和Android客户端.代码如下<script type="text/javascript"> var u ...

  9. 11 个使用 GNOME 3 桌面环境的理由

    11 个使用 GNOME 3 桌面环境的理由 作者: David Both 译者: LCTT geekpi | 2017-08-22 11:43   评论: 27 GNOME 3 桌面的设计目的是简单 ...

  10. 一个helloword hibernate配置以及查询

    搭建一个Hibernate环境,开发步骤: 1. 下载源码 版本:hibernate-distribution-3.6.0.Final 2. 引入jar文件 hibernate3.jar核心  +   ...