(Hadoop)Zookeeper

初识

简介

Zookeeper是一个分布式协调服务开源框架,它是由Google的Chubby开源实现。Zookeeper主要用来解决分布式集群中应用系统的一致性问题和单点故障问题,例如如何避免同时操作同一数据造成脏读的一致性问题等。

特性

Zookeeper具有全局数据一致性、可靠性、顺序性、原子性以及实时性,可以说Zookeeper的其他特性都是为满足Zookeeper全局数据一致性这一特性
在这里插入图片描述

  1. 全局一致性

     每个服务器都保存一份相同的数据副本,客户端无论连接到集群的任意节点上,看到的目录树都是一一致的(也就是数据的一致性)。这也是Zookeeper最重要的特性
    
  2. 可靠性

     如果消息(对目录结构的增删改查)被其中一台服务器接收,你那么将被所有的服务器接收
    
  3. 顺序性

     Zookeeper顺序性包含全局有序和偏序,其中全局有序指一台服务器上的A消息在B消息前发布,那么所有的服务器上的A消息都在B消息前发布;偏序是指,如果消息B在消息A后被同一个发布者发布,A必将排在B前面。无论全局有序还是偏序,都是保证全局数据一致性
    
  4. 数据更新原子性

     一次数据更新要么成功(半数以上节点成功),要么失败,不存在中间状态。
    
  5. 实时性

     Zookeeper保证客户端在一个时间间隔获取到的服务器的更新信息,或者服务器失效的的信息。
    

集群角色

Zookeeper集群是一个主从集群,它一般是由一个Leader(领导者)和多个Follower(跟随者)组成。此外,针对访问量比较大的Zookeeper集群,还可新增Observer(观察者)。Zookeeper集群中的三种角色各司其职,共同完成分布式协调服务。
在这里插入图片描述

Leader

Leader是Zookeeper集群工作的核心,也是事务性请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性,同时负责进行投票的发起和决议,以及更新系统状态

Follower

Follower负责处理客户端的非事务(读操作)请求,如果接收到客户端发来的事务性请求,则会转发给Leader,让Leader进行处理,同时还负责在Leader选举过程中参与投票。

Observer

Observer负责观察Zookeeper集群的最新状态的变化,并且将这些状态进行同步。对于非事务性请求可进行独立处理;对于事务性请求,则会转发给Leader服务器进行处理。它不参与任何形式的投票,只提供非事务性的服务

在这里插入图片描述

数据模型

数据存储结构

Zookeeper是由节点组成的,树中的每个节点被称为—Znode。每个节点都可以拥有子节点。每一个Znode默认能够存储1MB的数据,每个Znode都可以通过其路径唯一标识,如图中第三层的第一个Znode,,它的路径是/app1/p_1。Zookeeper数据模型中每个Znode都是由三部分组成,分别是stat、data、children在这里插入图片描述

Znode的类型

  • Znode的类型在创建时被指定,一旦创建就无法改变。
  • Znode有两种类型,分别是临时节点和永久节点。

临时节点

该生命周期依赖于创建它们的会话,一旦会话结束,临时节点将会被自动删除,也可以手动删除。虽然每个临时的Znode都会绑定一个客户端,但它们对所有的客户端还是可见的。需要注意的是临时节点不允许拥有子节点。

永久节点

该生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,它们才能被删除。

序列化

由于Znode的序列化特性,可以在创建时,用户在该Znode路径的结尾添加一个不断增加的序列号,序列对于此节点是唯一的,这样便会记录每个子节点创建的先后书序。格式为**%010d**(十位数字,没有值用0填充如0000000001),当计数值大于2^32-1时计数器会溢出。这样会存在4种类型的目录节点:

  1. PERSISTENT :永久节点
  2. EPHEMERAL : 临时节点
  3. PERSISTENT_SEQUENTIAL :序列化永久节点
  4. EPHEMERAL _SEQUENTIAL:序列化临时节点

Znode的属性

• 属性名称• 相关说明
• czxid• 节点被创建的时间
• ctime• 节点最后一次的修改的Zxid值
• mzxid• 节点最后一次的修改时间
• mtime• 与该节点的子节点最后一次修改的Zxid值
• pZxid• 子节点被修改的版本号
• cversion• 节点被创建的时间
• dataVersion• 数据版本号
• aclVersion• ACL(权限控制)版本号
• ephemeralOwner• 如果此节点为临时节点,那么该值代表这个节点拥有者的会话ID;否则值为0
• dataLength• 节点数据域长度
• numChildren• 节点拥有的子节点个数

Zookeeper的Watch机制

Watch机制简介

在ZooKeeper中,引入了Watch机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watch监听,当服务端的一些事件触发了这个Watch,那么就会向指定客户端发送一个事件通知,来实现分布式的通知功能

特点

  1. 一次性触发

     当Watch的对象发生改变是,也将会触发此对象上Watch所对应的时间,这样的监听是一次性的。
    
  2. 时间封装

     使用WatchedEvent对象来封装服务器端事件并传递。该对象包含了每个时间的三个基本属性,即通知状态,事件类型,节点路径。
    
  3. 异步发送

     Watch的通知事件是从服务器端异步发送到客户端的
    
  4. 先注册再触发

     必须由客户端去服务端注册监听,这样才会触发事件的监听,并通知给客户端。
    

Watch机制的通知状态和事件类型

同一个事件类型在不同的连接状态中代表的含义有所不同。常见的连接状态和事件类型如下所示。

• 连接状态• 状态含义• 事件类型• 事件含义
• Disconnected• 连接失败• NodeCreated• 节点被创建
• SyncConnected• 连接成功• NodeDataChanged• 节点数据变更
• AuthFailed• 认证失败• NodeChildrentChanged• 子节点数据变更
• Expired• 会话过期• NodeDeleted• 节点被删除

Zookeeper的选举机制

简介

Zookeeper为了保证各节点的协同工作,在工作时需要一个Leader角色,而Zookeeper默认采用FastLeaderElection算法,且投票数大于半数则胜出的机制。

服务器ID

设置集群myid参数时,参数分别为服务器1、服务器2、服务器3,编号越大FastLeaderElection算法中权重越大

选举状态

选举过程中,Zookeeper服务器有四种状态,分别为竞选状态(LOOKING)、随从状态(FOLLWING)、观察状态(OBSERVING)、领导者状态(LEADING)。

数据ID

是服务器中存放的最新数据版本号,该值越大则说明数据越新,在选举过程中数据越新权重越大。

逻辑时钟

逻辑时钟被称为投票次数,同一轮投票过程中逻辑时钟值相同,逻辑时钟起始值为0,每投一次票,数据增加。与接收到其它服务器返回的投票信息中数值比较,根据不同值做出不同判断

选举机制的类型

Zookeeper选举机制有两种类型,分别为全新集群选举和非全新集群选举。全新集群选举是新搭建起来的,没有数据ID和逻辑时钟的数据影响集群的选举;非全新集群选举时是优中选优,保证Leader是Zookeeper集群中数据最完整、最可靠的一台服务器。

全新集群选举

假设有5台机器分别是1~5,过程如下

  1. 服务器1启动,先给自己投票;其次,发投票信息,由于其它机器还没有启动所以它无法接收到投票的反馈信息,因此服务器1的状态一直属于竞选状态。
  2. 服务器2启动,先给自己投票;其次,在集群中启动Zookeeper服务的机器发起投票对比,它会与服务器1交换结果,由于服务器2编号大,服务器2胜出,服务器1会将票投给服务器2,此时服务器2的投票数并没有大于集群半数,两个服务器状态依旧是竞选状态。
  3. 服务器3启动,先给自己投票;其次,与之前启动的服务器1、2交换信息,服务器3的编号最大,服务器3胜出,服务器1、2会将票投给服务器3,此时投票数正好大于半数,所以服务器3成为领导者状态,服务器1、2成为追随者状态。
  4. 服务器4启动,先给自己投票;其次,与之前启动的服务器1、2、3交换信息,尽管服务器4的编号大,但是服务器3已经胜,所以服务器4只能成为追随者状态。
  5. 服务器5启动,同服务器4一样,均成为追随者状态。

非全新集群选举

  1. 统计逻辑时钟是否相同,逻辑时钟小,则说明途中可能存在宕机问题,因此数据不完整,那么该选举结果被忽略,重新投票选举。
  2. 统一逻辑时钟后,对比数据ID值,数据ID反应数据的新旧程度,因此数据ID大的胜出。
  3. 如果逻辑时钟和数据ID都相同的情况下,那么比较服务器ID(编号),值大则胜出。

Zookeeper分布式集群部署

Zookeeper分布式集群部署指的是ZooKeeper分布式模式安装。Zookeeper集群搭建通常是由2n+1台服务器组成,这是为了保证 Leader 选举(基于Paxos算法的实现)能够通过半数以上台服务器选举支持,因此,ZooKeeper集群的数量一般为奇数台

下载安装

由于Zookeeper集群运行需要Java环境支持,所以要提前安装JDK(对于jdk的下载安装这里不作赘述)。Zookeeper安装包的下载安装,具体步骤如下:

  1. 下载Zookeeper安装包。
  2. 解压到虚拟机
    在这里插入图片描述

配置

修改Zookeeper的配置文件。

在这里插入图片描述

先将zoo_sample.cfg配置文件重命名为zoo.cfg,然后指定dataDir目录、配置服务器编号与主机名映射关系、设置与主机连接的心跳端口和选举端口。

在这里插入图片描述

创建myid文件。

根据配置文件zoo.cfg设置的dataDir目录,创建zkdata文件夹并创建myid文件,该文件里面的内容就是服务器编号。

mkdir -p /export/data/zookeeper/zkdata
echo 1 > myid

在这里插入图片描述

配置环境变量

vi /etc/profile


source /etc/profile

在这里插入图片描述

分发

  • 分发Zookeeper
[root@hadoop01 opt]# scp -r ./zookeeper/ hadoop02:`pwd`
[root@hadoop01 opt]# scp -r ./zookeeper/ hadoop03:`pwd`
  • 分发myid文件,并将myid 的文件改为2、3
scp -r /export  hadoop02:/export
scp -r /export  hadoop02:/export

vi myid
  • 分发环境变量
scp -r /etc/profile hadoop02:/etc/profile
scp -r /etc/profile hadoop03:/etc/profile

# 分别source使环境变量生效
source /etc/profile

Zookeeper服务的启动和关闭

启动Zookeeper服务

  1. 启动
zkServer.sh start

在这里插入图片描述

  • 注意:Zookeeper3.5版本要下载bin版本否则会出现启动失败。Zookeeper的日志显示找不到主类。
  1. 查看角色
zkServer.sh status

在这里插入图片描述
在这里插入图片描述

关闭Zookeeper

分别在机器上执行

zkServer.sh stop

在这里插入图片描述在这里插入图片描述

ZookeeperShell操作

介绍

  • Zookeeper命令行工具类似于Linux的Shell环境,能够简单地实现对Zookeeper进行访问、数据创建、数据修改等的一系列操作。
常用命令命令描述
ls /使用ls命令来查看Zookeeper中所包含的内容
ls2 /查看当前节点数据并能看到更新次数等数据
create /zk “test”在当前目录创建一个新的Znode节点“zk”以及与它关联的字符串
get /zk获取zk所包含的信息
set /zk “zkbak”对zk所关联的字符串进行设置
delete /zk将节点Znode删除
rmr将节点Znode递归删除
help帮助命令

通过Shell命令操作Zookeeper

启动Zookeeper

  1. (启动Hadoop服务及yarn服务之后)启动Zookeeper集群
    • 在所有集群键入
zkServer.sh start
  1. 连接Zookeeper服务,在屏幕输出“welcome to Zookeeper!”等信息。
zkCli.sh -server 地址:端口号

在这里插入图片描述

操作Zookeeper

  1. 显示所有操作命令
help

在这里插入图片描述

  1. 查看当前Zookeeper包含所有的内容
ls /

在这里插入图片描述

  1. 查看当前数据节点
ls2 /

在这里插入图片描述

  1. 创建节点
create [-s] [-e] path data acl
参数名称说明
-s表示开启节点的序列化特性(会在节点名字后加一个10位的数字)
-e表示开启临时节点的特性,不指定则为永久节点
path创建的路径
data节点数据,因为Znode可以象目录一样存在,也可一项文件一样保存数据
acl进行权限控制(一般不需要了解)
1. 创建序列化永久节点
create -s /testnode test
2. 创建临时节点
create -e /testnode-temp testemp
3. 创建永久节点
create /testnode-p testp

在这里插入图片描述

  1. 获取节点
ls path [watch]
gat path [watch]
ls2 path [watch]

在这里插入图片描述
6. 修改节点

set path data [version]
参数名称说明
data要修改的新内容
version表示数据版本

在这里插入图片描述
7. 监听节点

  • 监听节点的变化,三个过程。

      1. 客户端向服务器注册Watch
      2. 服务端事件发生触发Watch
      3. 客户端回调Watch的到触发事件的情况
    
  • 客户端个向服务器注册Watch,在服务器hadoop01客户端的命令行输出命令

get /testnode-temp watch

在这里插入图片描述

  • 服务端事件发生触发Watch,在服务器hadoop02客户端的名称行键入(要进入hadoop01的Zookeeper客户端)
zkCli.sh -server hadoop01:2181
set /testnode-temp testwatch

在这里插入图片描述

  • 产生效果
    在这里插入图片描述
  1. 删除节点
1. 普通删除
delete path [version]
2. 递归删除
rmr path [version]

在这里插入图片描述

  • delete删除当节点存在子节点就无法删除该节点。使用rmr可以递归删除节点,无论有没有子节点。

Zookeeper的JavaAPI操作

介绍

Zookeeper API包含五个包:

  1. org.apache.zookeeper
  2. org.apache.zookeeper.data
  3. org.apache.zookeeper.server
  4. org.apache.zookeeper.server.quorum
  5. org.apache.zookeeper.server.upgrade

其中 org.apache.zookeeper包含Zookeeper类,是最常用的类文件。主要使用了Zookeeper服务,应用程序就需要先创建一个Zookeeper实例对象,一但客户端与Zookeeper服务建立了连接,Zookeeper系统将会为此链接分配一个会话的ID值,并且客户端会周期性的向服务器发送心跳包,来保持会话的链接

  • Zookeeper类常用方法
方法名称描述
create创建节点
delete删除节点
exists判断节点是否存在
get/setData获取/修改节点
get/Children获取指定节点下的所有子节点列表

通过Java API操作Zookeeper

添加依赖

<dependency>
	<groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.14</version>
</dependency>

在这里插入图片描述

操作

在src目录下创建cn.zcx.zookeeper包下创建ZookeeperTest.java
在这里插入图片描述

public class ZookeeperTest {
    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        // 步骤1:创建Zookeeper客户端
        /*
        * 参数1:zk地址,参数2:会话超时时间(与系统默认一致);参数3:监视器
        * */
        ZooKeeper zk = new ZooKeeper("192.168.198.131:2181,192.168.198.132:2181,192.168.198.133:2181,192.168.198.134:2181,192.168.198.135:2181", 3000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("事件发生的路径:"+watchedEvent.getPath());
                System.out.println("事件类型:"+watchedEvent.getType());
                System.out.println("事件的通知状态:"+watchedEvent.getState());
            }
        });
        // 步骤二:创建目录节点
        /*
        * 参数1:要创建的节点路径,参数2:节点数据,参数3:节点权限,参数4:节点类型
        * */
//        zk.create("/testRootPath1","testRootData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
        // 步骤三:创建子目录节点
//        zk.create("/testRootPath1/testChildPathOne","testChildPathOne".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
        // 步骤四:获取目录节点数据
        /*
        * 参数1:存储数据的路径,参数2:是否监控此节点(true或false),参数3:stat节点的统计信息
        * */
//        System.out.println("testRootPath1节点的数据"+new String(zk.getData("/testRootPath1",false,null)));
        // 步骤五:获取子目录节点数据
//        System.out.println(zk.getChildren("/testRootPath1",true));
        // 步骤六:修改子目录数据使监听触发
        /*
        * 参数1:存储子节点数据的路径,参数2:要修改的数据,参数3:与其匹配的版本(-1为匹配任何节点的版本)
        * */
//        zk.setData("/testRootPath1/testChildPathOne","zcx111".getBytes(),-1);
        // 步骤七:判断目录节点是否存在
//        System.out.println("目录节点状态:"+zk.exists("/testRootPath1",true));
        // 步骤八:删除子目录节点
//        zk.delete("/testRootPath1/testChildPathOne",-1);
        // 步骤八:删除目录节点
        zk.delete("/testRootPath1",-1);
    }
}

Zookeeper典型应用场景

数据发布与订阅

数据发布与订阅模型,即所谓的全局配置中心,顾名思义就是发布者将需要全局统一管理的数据发布到Zookeeper节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,服务式服务框架的服务地址列表等就非常适合使用。

应用场景

  1. 应用中用到的一些配置信息放到Zookeeper上进行集中管理。
  2. 分布式搜索服务中,索引的元信息和服务器集群机器的节点状态存放在Zookeeper的一些指定节点,供各个客户端订阅使用。
  3. 分布式日志收集系统中,这个系统的核心工作是收集分布在不同机器的日志。
  4. 系统中有些信息需要动态获取,并且还会存在人工手动去修改这个信息的发问。

统一命名服务

命名服务也是分布式系统中比较常见的一类场景。在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源服务的地址,提供者等信息。

应用场景

  1. 阿里开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表

分布式锁

  1. 分布式锁,这个主要得益于ZooKeeper为我们保证了数据的强一致性。
  2. 锁服务可以分为两类,一个是保持独占,另一个是控制时序。
  3. 保持独占:就是所有试图来获取这个锁的客户端,最终只有一个客户端可以成功获得这把锁,从而执行相应操作;
  4. 控制时序:则是所有试图来获取锁的客户端,最终都会被执行,存在全局时序,客户端在临时非序列化节点下创建临时序列化节点,根据序列号大小进行时序性操作。

应用场景

  1. 当所有客户端都去创建临时非序列化节点,那么最终成功创建的客户端也拥有了这把锁,拥有了访问该数据的权限,当操作完毕后,断开与Zookeeper连接,那该临时节点就会被删除,如果其他客户端需要操作这个文件,客户端只需监听这个目录是否存在即可。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值