大数据技术之Hadoop(五)——Zookeeper

目录

 

一、认识Zookeeper

1、概念

2、特性

3、集群角色

二、数据模型

1、数据存储结构

2、Znode的类型

3、Znode的属性

 

三、Zookeeper的Watch机制

1、Watch机制的认识

2、Watch机制的通知状态和时间类型

四、Zookeeper的选举机制

1、选举机制的认识

2、选举机制的类型

五、Zookeeper分布式集群部署

1、Zookeeper安装包的下载安装

(1)下载Zookeeper安装包

(2)上传Zookeeper安装包

 (3)解压Zookeeper安装包

2、Zookeeper相关配置

(1)修改Zookeeper的配置文件

(2)创建目录及 myid 文件

(3)配置环境变量

(4)分发zookeeper文件至其他服务器

(5)修改hadoop02.bgd01、hadoop03.bgd01 上的myid文件内容

(6)在3台主机上使环境变量生效

3、 Zookeeper服务的启动与关闭

(1)启动Zookeeper服务

(2)查看Zookeeper的角色

 (3)关闭Zookeeper服务

六、Zookeeper的Shell操作

1、通过Shell命令操作Zookeeper

(1)显示所有操作指令

(2)查看当前Zookeeper所包含的内容

(3)查看当前节点数据

(4)创建节点

(5)获取节点

(6)修改节点

(7)监听节点

(8)删除节点

七、Zookeeper的Java API 操作

(1)配置相关依赖

(2)操作Zookeeper


        Zookeeper的安装包已经放在百度网盘有需要可自行提取。

http://链接: https://pan.baidu.com/s/1cxNjkDg8Jp1HNKQGhC3_-w?pwd=v443 提取码: v443

一、认识Zookeeper

1、概念

        Zookeeper是一个分布式协调框架,主要用来解决分布式集群中应用系统的一致性问题,例如如何避免同时操作同一数据造成脏读的问题等。本质上是一个分布式的小文件存储系统,提供基于类似文件系统的目录树方式的数据存储,并且可以对树中的节点进行有效管理,从而用来维护和监控存储的数据的状态变化。通过监控这些数据状态的变化,从而达到基于数据的集群管理,如统一命名服务,分布式配置管理,分布式消息队列,分布式锁,分布式协调等功能。

2、特性

(1)全局数据唯一性

        每个服务器都保存一份相同的数据副本,客户端连接到集群的任意节点上,看到的目录树都是一致的(也就是数据都是一致的)。

(2)可靠性

        如果消息(对于目录的增删改查等操作)被其中一台服务器接收,那么将被所有的服务器接收。

(3)顺序性

        zookeeper的顺序性主要分为全局有序和偏序两种,全局有序指如果在一台服务器上消息A在消息B前发布,则在所有服务器上消息A都将在消息B前被发布;偏序是指如果一个消息B在消息A后被同一个发送者发布,A必将排在B前面,无论全局有序还是偏序,其目的都是为了保证Zookeeper全局数据一致。

(4)数据更新原子性

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

(5)实时性

        Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失败的信息。

3、集群角色

(1)Leader

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

(2)Follower

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

(3)Observer

        负责观察Zookeeper集群的最新状态变化,并且将这些状态进行同步,对于非事物性请求可以可以进行独立处理;对于事物性请求,则会转发给Leader服务器进行处理。它不会参与任何形式的投票,只提供非事物性服务,通常用作于在不影响集群事物的前提下,提升集群的非事物处理能力(提高集群读的能力,也降低了集群选主的复杂程度)。

二、数据模型

1、数据存储结构

        Zookeeper中数据存储结构和标准文件系统非常类似,拥有一个层次的命名空间,也是使用斜杠“ / ” 进行分隔的,两者都是采用树状层次结构。但标准文件系统是由文件夹和文件组成的树,而Zookeeper是由节点组成的树,树中的每个节点被称为Znode,每个节点都可以拥有子节点。每一个Znode默认能够存储1MB的数据,每个Znode都可以通过其路径唯一标识。

2、Znode的类型

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

(1)临时节点

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

(2)永久节点

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

       

        由于 Znode 的序列化特性,在创建节点时,用户可以请求在该 Znode 的路径结尾添加一个不断增加的序列号,序列号对于此节点的父节点来说是唯一的,这样便会记录每个子节点创建的先后顺序。它的格式为“%010d”(10 位数字,没有数值的数位用0补充,如0000000001)。当计数值大于23-1时,计数器将会溢出。这样便会存在4种类型的目录节点,分别对应如下。

PERSISTENT:永久节点;

EPHEMERAL:临时节点;

·PERSISTENT_SEQUENTIAL:序列化永久节点;

EPHEMERAL SEQUENTIAL:序列化临时节点。

3、Znode的属性

属性名称 属性描述
czxid 节点被创建的Zxid值
ctime 节点被创建的时间
mzxid 节点最后一次修改的Zxid值
mtime 节点最后一次修改的时间
pZxid 与该节点的子节点最后一次修改的Zxid值
cversion 子节点被修改的版本号
data Version 数据版本号
acl Version ACL版本号
ephemeralOwner 如果此节点为临时节点,那么该值代表这个节点拥有者的会话ID;值为0
dataLength 节点数据域长度
numChildren 节点用的子节点个数

 

三、Zookeeper的Watch机制

1、Watch机制的认识

        ZooKeeper 提供了分布式数据发布/订阅功能,一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使他们能够做出相应的处理。在ZooKeeper中,引入了Watch 机制来实现这种分布式的通知功能。ZooKeeper允客户端向服务端注册一个 Watch 监听,当服务端的一些事件触发了这个 Watch,那么就人向指定客户端发送一个事件通知,来实现分布式的通知功能。

(1)一次性触发

        当 Watch 的对象发生改变时,将会触发此对象上 Watch 所对应的事件,这种监听是一次性的,后续再次发生同样的事件,也不会再次触发。

(2)事件封装

        Zookeeper 使用WatchedEvent 对象来封装服务端事件并传递。该对象包含了每个事件的3个基本属性,即通知状态(keeperState)、事件类型(EventType)和节点路径(path)。

(3)异步发送

        Watch的通知事件是从服务端异步发送到客户端的。

(4)先注册再触发

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

2、Watch机制的通知状态和时间类型

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

四、Zookeeper的选举机制

1、选举机制的认识

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

(1)服务器ID

        这是在配置集群时设置的myid参数文件,且参数分别表示为服务器1、服务器2和服务3,编号越大在FastLeaderElection算法中的权重越大。

(2)选举状态

        在选举过程中,Zookeeper服务状态有4种状态,它们分别为竞选状态(LOOKING)、随从状态(FOLLOWING,同步leader状态,参与投票)、观察状态(OBSERVING,同步leader状态,不参与投票)和领导者状态(LEADING)。

(3)数据ID

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

(4)逻辑时钟

        通俗地讲.逻辑时钟被称为投票次数,同一轮投票过程中的逻辑时钟值是相同的,逻辑时钟起始值为0,每投完一次票,这个数据就会增加。然后,与接收到其他服务器返回的票信息中的数值相比较,根据不同的值做出不同的判断。如果某台机器宕机,那么这台机务不会参与投票,因此逻辑时钟也会比其他的低。

2、选举机制的类型

        Zookeeper 选举机制有两种类型,分别为全新集群选举和非全新集群选举。

(1)全新集群选举

        全新集群选举是新搭建起来的,没有数据ID和逻辑时钟来影响集群的选举。假设,目前有5台服务器,它们的编号分别是1~5,按编号依次启动Zookeeper服务。下面来讲解全新集群选举的过程

步骤1:服务器1启动,首先,会给自己投票;其次,发投票信息,由于其他机器还没有启动所以它无法接收到投票的反馈信息,因此服务器1的状态一直属于LOOKING状态。

步骤2:服务器2启动,首先,会给自己投票;其次,在集群中启动 Zookeeper 服务的机器发起投票对比,这时它会与服务器1交换结果,由于服务器2的编号大,所以服务器2胜出,此时服务器1会将票投给服务器2,但此时服务器2的投票数并没有大于集群半数(2<5/2),所以两个服务器的状态依然是 LOOKING 状态。

步骤3:服务器3启动,首先,会给自己投票;其次,与之前启动的服务器1和服务器2交换信息,由于服务器3的编号最大,所以服务器3胜出,那么服务器1和2会将票投给服务器3,此时投票数正好大于半数(3>5/2),所以服务器3成为领导者状态,服务器1和2成为追随者状态。

步骤4:服务器4启动,首先,给自己投票;其次,与之前启动的服务器12和3交换信息,尽管服务器4的编号大,但是服务器3已经胜出。所以服务器4只能成为追随者状态。

步骤5:服务器5启动,同服务器4一样,均成为追随者状态。

(2)非全新集群选举

        对于正常运行的 Zookeeper集群,一旦中途有服务器宕机,则需要重新选举时,选举的过程中就需要引入服务器ID、数据ID和逻辑时钟。这是由于Zookeeper集群已经运行过一段时间,那么服务器中就会存在运行的数据。下面来讲解非全新集群选举的过程。

步骤1:首先,统计逻辑时钟是否相同,逻辑时钟小,则说明途中可能存在宕机问题,因此数据不完整,那么该选举结果被忽略,重新投票选举;

步骤2:其次,统一逻辑时钟后,对比数据ID值,数据ID反血数据的新旧程度,因此数据ID大的胜出;

步骤3:如果逻辑时钟和数据ID都相同的情况下,那么比较服务器 ID(编号),值大购胜出;

        简单地讲,非全新集群选举时是优中选优,保证 Leader 是Zookeeper 集群中数据最完整、最可靠的一台服务器。

五、Zookeeper分布式集群部署

1、Zookeeper安装包的下载安装

(1)下载Zookeeper安装包

        下载地址:http://172.16.1.89/tools/HadoopInstall/zookeeper/apache-zookeeper-3.7.1-bin.tar.gz

或在阿里云镜像: http://mirrors.aliyun.com/apache/zookeeper/下载相关的版本。

(2)上传Zookeeper安装包

确保虚拟机安装了上传文件工具rz软件,没有执行以下指令。
yum install lrzsz -y

将安装包上传到指定目录下,这里作者上传到/export/software目录下。
cd /export/software

rz

 (3)解压Zookeeper安装包

解压软件包到指定目录下,这里作者解压到/export/servers目录下。
tar -zxvf apache-zookeeper-3.7.1-bin.tar.gz -C /export/servers/

对于软件包进行重命名,便于后续管理。
mv /export/servers/apache-zookeeper-3.7.1-bin /export/servers/zookeeper

2、Zookeeper相关配置

(1)修改Zookeeper的配置文件

进入Zookeeper配置目录:
cd /export/servers/zookeeper/conf

执行如下命令,复制文件
cp zoo_sample.cfg zoo.cfg

编辑文件 zoo.cfg
vi zoo.cfg
    
将行 “dataDir=/tmp/zookeeper” 修改为:
dataDir=/export/data/zookeeper/zkdata
dataLogDir=/export/data/zookeeper/zklog

在文件末尾添加如下几行:

#配置Zookeeper集群的服务器编号及对应的主机名、通信端口号(心跳端口号)和选举端口号
server.1=hadoop01.bgd01:2888:3888
server.2=hadoop02.bgd01:2888:3888
server.3=hadoop03.bgd01:2888:3888

注意:这里的主机名以自己的虚拟机名字为准

73954b3a4e2e4c3d9a910758b075c0fc.png 

624e4a2d775a40f3b9e6d2c236ab425b.png 

(2)创建目录及 myid 文件

创建目录 /export/data/zookeeper/zkdata、/export/data/zookeeper/zklog
mkdir -p /export/data/zookeeper/zkdata
mkdir -p /export/data/zookeeper/zklog

进入 /export/data/zookeeper/zkdata 目录
cd /export/data/zookeeper/zkdata

创建myid文件
echo 1 > myid

(3)配置环境变量

在/etc/profile文件中配置Zookeeper环境变量
export ZK_HOME=/export/servers/zookeeper
export PATH=$PATH:$ZK_HOME/bin

79cbe41cd24b42d18d8872d1284421b9.png 

(4)分发zookeeper文件至其他服务器

scp -r /export/servers/zookeeper hadoop02.bgd01:/export/servers/
scp -r /export/servers/zookeeper hadoop03.bgd01:/export/servers/

scp -r /export/data/zookeeper  hadoop02.bgd01:/export/data/
scp -r /export/data/zookeeper  hadoop03.bgd01:/export/data/

scp -r /etc/profile hadoop02.bgd01:/etc/profile 
scp -r /etc/profile hadoop03.bgd01:/etc/profile 

(5)修改hadoop02.bgd01、hadoop03.bgd01 上的myid文件内容

hadoop02.bgd01上/export/data/zookeeper/zkdata/myid的内容为2
vi /export/data/zookeeper/zkdata/myid

hadoop03.bgd01上/export/data/zookeeper/zkdata/myid的内容为3
vi /export/data/zookeeper/zkdata/myid

(6)在3台主机上使环境变量生效

source /etc/profile

3、 Zookeeper服务的启动与关闭

(1)启动Zookeeper服务

分别在三台虚拟机上执行以下指令。
zkServer.sh start

34df53a2f6544b4e8e47df1f65134735.png 

(2)查看Zookeeper的角色

分别在三台机上执行以下指令。
zkServer.sh status

329d62fafa5944359c4836f1dcec756a.png 

4ef0efd649194613b7c1ca5232da0e73.png 

7580514d257f4a92bf486d5ef828ec00.png 

 (3)关闭Zookeeper服务

分别在三台虚拟上执行以下指令。
zkServer.sh stop

9925e87b88434663b5ffcd63d092d9e7.png 

六、Zookeeper的Shell操作

1、通过Shell命令操作Zookeeper

        启动并连接Zookeeper服务。

zkServer.sh start

zkCli.sh -server localhost:2181

a7b1c171bca842228f131b26d86646f2.png 

(1)显示所有操作指令

在客户端输入help,会输出所有可用的Shell指令。
help

(2)查看当前Zookeeper所包含的内容

6d186307a9b243718b690140c984aa56.png

        注意:根目录下有一个自带的/zookeeper子节点,用来保存Zookeeper配置管理信息,不要随便删除。

(3)查看当前节点数据

ls2 /

(4)创建节点

create [-s] [-e] path data acl

其中-s表示是否开启节点的序列化特性,-e表示开启临时节点特性,不指定则表示永久节点;Path表示路径,data表示创建节点数据,这是因为Znode可以像目录一样存在也可以像文件一样保存数据,acl用来进行权限控制。

创建序列化永久节点
create -s /testnode test

创建临时节点
create -e /testnode-temp testtemp

创建永久节点
create /testnode-p testp

a55285f2d8fd4163bdb329bd3ca2f68d.png 

(5)获取节点

ls Path [watch]
ls2 Path [watch]
get Path [watch]

其中get命令可以获取Zookeeper指定节点的数据内容和属性信息

a29a4ce5b77845eaa66ea07887cef510.png 

(6)修改节点

set path data [version]

data表示修改的新内容,version表示版本。

示例如下:
set /testnode-temp 123

c37d4c32fb3d470cb9fa5ada6807ae20.png 

(7)监听节点

监听节点也就是监听节点的变化,可以概括为3个过程。客户端向服务端注册 Watch服务端事件发生触发 Watch、客户端回调 Watch 得到触发事件的情况。
首先,客户端向服务端注册 Watch,在服务器 hadoop01客户端的命令行输人命令,具体命令如下:
get /testnode temp watch

其次,服务端发生事件触发 Watch,在服务器 hadoop02 客户端的命令行输入命令,具体命令如下:

set /testnode-temp testwatch

最后,客户端回调 Watch 得到触发事件的情况。

(8)删除节点

delete path [version]
rmr path [version]

其中,使用delete命令删除节点时,要删除的节点存在子节点,就无法删除该节点,必须先删除子节点,才能删除父节点;rmr命令递归删除节点,无论该节点是否存在子节点。

七、Zookeeper的Java API 操作

(1)配置相关依赖

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

(2)操作Zookeeper

package cn.itcast.zookeeper;

import org.apache.zookeeper.*;

public class Zookeepertext {
    public static void main(String[] args) throws Exception {
        // 初始化ZooKeeper实例(zk地址、会话超时时间,与系统默认一致, watcher)
        ZooKeeper zk = new ZooKeeper("localhost:2181", 30000, new Watcher() {
            public void process(WatchedEvent event) {
                System.out.println("事件类型为: " + event.getType());
                System.out.println("事件发生的路径: " + event.getPath());
                System.out.println("通知状态为: " + event.getState());
            }
        });
        // 创建一个目录节点
        zk.create("/testRootPath", "testRootData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        // 创建一个子目录节点
        zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
        System.out.println(new String(zk.getData("/testRootPath", false, null)));
        // 取出子目录节点列表
        System.out.println(zk.getChildren("/testRootPath", true));
        // 修改子目录节点数据
        zk.setData("/testRootPath/testChildPathOne", "modifyChildDataOne".getBytes(), -1);
        //判断目录节点是否存在
        System.out.println("目录节点状态: [" + zk.exists("/testRootPath", true) + "]");
        // 创建另外一个子目录节点
        zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
        System.out.println(new String(zk.getData("/testRootPath/testChildPathTwo", true, null)));
        // 删除子目录节点
        zk.delete("/testRootPath/testChildPathTwo", -1);
        zk.delete("/testRootPath/testChildPathOne", -1);
        // 删除父目录节点
        zk.delete("/testRootPath", -1);
        zk.close();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_63507910/article/details/128571275