一、数据采集模块
Linux基本配置
【1】Linux环境搭建
1).修改MAC地址 方法1:vim /etc/udev/rules.d/70-persistent-net.rules 删除eth0,将eth1修改为eth0 方法2:rm -rf /etc/udev/rules.d/70-persistent-net.rules 2).修改IP vim /etc/sysconfig/network-scripts/ifcfg-eth0 修改以下代码: ONBOOT=yes BOOTPROTO=static 添加以下代码: IPADDR=192.168.100.100 NETMASK=255.255.255.0 GATEWAY=192.168.100.2 DNS1=8.8.8.8 3).修改主机名 vim /etc/sysconfig/network 4).配置hosts vim /etc/hosts 192.168.100.100 node01 (根据自己需求配置映射关系) 5).关闭防火墙(CentOS7以下版本) 暂时关闭:service iptables stop 永久关闭:chkconfig iptables off 6).关闭selinux vim /etc/selinux/config 将SELINUX设置为disabled 7).添加用户 useradd zsy passwd zsy vim /etc/sudoers +92 zsy ALL=(ALL) NOPASSWD: ALL su - zsy 8).SSH免密钥 ssh-keygen 然后敲四下回车 ssh-copy-id localhost
【2】Hadoop环境搭建
1)基础环境创建
[node01] cd ~ mkdir bin cd bin vim xsync =======================脚本如下======================== #!/bin/bash #1 获取输入参数个数,如果没有参数,直接退出 pcount=$# if((pcount==0)); then echo no args; exit; fi #2 获取文件名称 p1=$1 fname=`basename $p1` echo fname=$fname #3 获取上级目录到绝对路径 pdir=`cd -P $(dirname $p1); pwd` echo pdir=$pdir #4 获取当前用户名称 user=`whoami` #5 循环 for((host=101; host<104; host++)); do echo ------------------- hadoop$host -------------- rsync -rvl $pdir/$fname $user@hadoop$host:$pdir done =======================脚本如上======================== chmod 770 xsync sudo rm -rf /opt/* sudo mkdir /opt/modules sudo mkdir /opt/software sudo mkdir -p /opt/tmp/logs sudo chown zsy:zsy -R /opt xsync /opt/* [node02/node03] sudo chown zsy:zsy -R /opt
2)JDK安装
注意: 安装之前,请先删除系统自带的JDK
[node01] tar -zxf /opt/software/jdk-8u144-linux-x64.tar.gz -C /opt/modules sudo vim /etc/profile.d/java.sh export JAVA_HOME=/opt/modules/jdk1.8.0_144 export PATH=$PATH:$JAVA_HOME/bin source /etc/profile xsync /opt/modules/jdk1.8.0_144 sudo scp /etc/profile.d/java.sh node02:/etc/profile sudo scp /etc/profile.d/java.sh node03:/etc/profile [node02/node03] source /etc/profile
注意:可以看到,我在上面添加的JDK环境变量是在/etc/profile.d目录下创建了一个以.sh结尾的文件,那么为什么可以这么做呢?
我们首先说一下环境变量的配置方式有哪些
1)修改/etc/profile文件:用来设置系统环境参数,比如$PATH,这里面的环境变量是对系统内所有用户生效。使用bash命令,需要source /etc/profile一下
2)修改~/.bashrc文件:针对某一个特定的用户,环境变量的设置只对该用户自己有效,使用bash命令,只要以该用户身份运行命令行就会读取该文件,该文件会去加载/etc/bashrc文件,该文件会遍历/etc/profile.d文件下的以.sh文件结尾的文件,将其中的环境变量添加到/etc/bashrc文件中,所以我们把配置的环境变量添加到/etc/profile.d目录下
3)说明:
登录式Shell:采用用户名登录,会自动加载/etc/profile
非登录式Sehll:采用ssh登录,不会自动加载/etc/profile,会自动加载~/.backrc
3)Zookeeper安装
一、ZooKeeper概述
【1】Zookeeper简介
- (1)Zookeeper是一个分布式协调服务的开源框架,主要用来解决分布式集群中应用系统的一致性问题
- (2)ZooKeeper本质上是一个分布式的小文件存储系统。提供基于类似于文件系统的目录树方式的数据存储,并且可以对树中的节点进行有效管理。从而用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理
- (3)Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应,从而实现集群中类似Master/Slave管理模式
- (4)Zookeeper = 文件系统 + 通知机制
【2】Zookeeper特性
- (1)
全局数据一致:集群中每个服务器保存一份相同的数据副本,client无论连接到哪个服务器,展示的数据都是一致的,这是最重要的特征 - (2)
可靠性:如果消息被其中一台服务器接受,那么将被所有的服务器接受 - (3)
顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面 - (4)
数据更新原子性:一次数据更新要么成功(半数以上节点成功),要么失败,不存在中间状态 - (5)
实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息
【3】Zookeeper集群角色
Leader:
1.Zookeeper集群工作的核心
2.事务请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性
3.集群内部各个服务器的调度者
4.对于create,setData,delete等有写操作的请求,则需要统一转发给leader处理,
leader需要决定编号、执行操作,这个过程称为一个事务
Follower:
1.处理客户端非事务(读操作)请求,转发事务请求给Leader
2.参与集群Leader选举投票
3.此外,针对访问量比较大的zookeeper集群,还可新增观察者角色
Observer:
1.观察者角色,观察Zookeeper集群的最新状态变化并将这些状态同步过来,其对于非事务请求可以进行独立处理,
对于事务请求,则会转发给Leader服务器进行处理
2.不会参与任何形式的投票只提供非事务服务,通常用于在不影响集群事务处理能力的前提下提升集群的非事务处理能力
二、ZooKeeper安装
安装zookeeper的注意事项: 安装前需要安装好jdk 检测集群时间是否同步 检测防火墙是否关闭 检测主机 ip映射有没有配置 ##下载安装包、解压 下载地址: CDH版本:http://archive.cloudera.com/cdh5/cdh/5/zookeeper-3.4.5-cdh5.14.0.tar.gz apache版本:https://archive.apache.org/dist/zookeeper/
【1】解压tar包
tar -zxf zookeeper-3.4.5-cdh5.14.0.tar.gz ../servers/
【2】配置环境变量
vim /etc/profile.d/zookeeper.sh export ZOOKEEPER_HOME=/export/servers/zookeeper export PATH=$PATH:$ZOOKEEPER_HOME/bin source /etc/profile
【3】修改配置文件
cd $ZOOKEEPER_HOME/conf mv zoo_sample.cfg zoo.cfg vim zoo.cfg
【4】添加myid
创建在 zoo.cfg 中指定的 dataDir 目录 mkdir /export/servers/zookeeper/zkdata 进入到目录 cd /export/servers/zookeeper/zkdata 给当前节点添加 myid echo 1 > myid
【5】分发zookeeper
scp -r zookeeper node02:`pwd` 分发完后根据需求修改 myid 文件中的值大小
【6】启动zookeeper
每台节点使用命令 zkServer.sh start 进行启动 然后使用命令 zkServer.sh status 进行查看状态
zoo.cfg文件中的 配置参数解读
- 1)
tickTime:通信心跳数,Zookeeper服务器心跳时间,单位毫秒
Zookeeper使用的基本时间,服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个tickTime时间就会发送一个心跳,时间单位为毫秒
它用于心跳机制,并且设置最小的session超时时间为两倍心跳时间
(session的最小超时时间是2 * tickTime) - 2)
initLimit:LF初始通信时限
集群中的follower跟随者服务器(F)与leader领导者服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量),用它来限定集群中的Zookeeper服务器连接到Leader的时限
投票选举新leader的初始化时间
Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态
Leader允许F在initLimit时间内完成这个工作 - 3)
syncLimit:LF同步通信时限
集群中Leader与Follower之间的最大响应时间单位,假如响应超过syncLimit * tickTime,
Leader认为Follwer死掉,从服务器列表中删除Follwer
在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态
如果L发出心跳包在syncLimit之后,还没有从F那收到响应,那么就认为这个F已经不在线了 - 4)
dataDir:数据文件目录+数据持久化路径
保存内存数据库快照信息的位置,如果没有其他说明,更新的事务日志也保存到数据库 - 5)
clientPort:客户端连接端口,监听客户端连接的端口
三、ZooKeeper Shell
【1】客户端连接
运行 zkCli.sh 或 zkCli.sh –server ip 进入命令行工具 输入help,输出zk shell提示:
【2】shell基本操作
(1)创建节点
语法:create [-s] [-e] path data acl
其中,-s 指定为序列化节点 、 -e 指定为临时节点 ; 若不指定,则表示永久非序列化节点,acl用来进行权限控制
(2)读取节点
与读取相关的命令有 ls 命令 和 get 命令 1.ls 命令可以列出Zookeeper指定节点下的所有子节点,只能查看指定节点下的第一级的所有子节点 2.get 命令可以获取Zookeeper指定节点的数据内容和属性信息 语法: ls path [watch] get path [watch] ls2 path [watch]
(3)更新节点
语法:set path data [version]
data就是要更新的新内容,version表示数据版本
现在dataVersion已经变为2了,表示进行了2次更新
(4)删除节点
语法:delete path [version]
若删除节点存在子节点,那么无法删除该节点,必须先删除子节点,再删除父节点
语法:Rmr path
递归删除节点
(5)其他节点相关命令
语法:setquota -n|-b val path
对节点增加限制
n:表示子节点的最大个数
b:表示数据值的最大长度
val:子节点最大个数或数据值的最大长度
path:节点路径
语法:listquota path
列出指定节点的quota
语法:delquota [-n|-b] path
删除quota
语法:history
列出命令历史
语法:redo 编号
该命令可以重新执行指定命令编号的历史命令,命令编号可以通过history查看
四、ZooKeeper 数据模型
ZooKeeper的数据模型,在结构上和标准文件系统的非常相似,拥有一个层次的命名空间,都是采用树形层次结构,ZooKeeper树中的每个节点被称为Znode。和文件系统的目录树一样,ZooKeeper树中的每个节点可以拥有子节点。但也有不同之处:
- (1)
Znode兼具文件和目录两种特点。既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分,并可以具有子Znode。用户对Znode具有增、删、改、查等操作(权限允许的情况下) - (2)
Znode具有原子性操作,读操作将获取与节点相关的所有数据,写操作也将替换掉节点的所有数据。另外,每一个节点都拥有自己的ACL(访问控制列表),这个列表规定了用户的权限,即限定了特定用户对目标节点可以执行的操作 - (3)
Znode存储数据大小有限制。ZooKeeper虽然可以关联一些数据,但并没有被设计为常规的数据库或者大数据存储,相反的是,它用来管理调度数据,比如分布式应用中的配置文件信息、状态信息、汇集位置等等。这些数据的共同特性就是它们都是很小的数据,通常以KB为大小单位。ZooKeeper的服务器和客户端都被设计为严格检查并限制每个Znode的数据大小至多1M,当时常规使用中应该远小于此值 - (4)
Znode通过路径引用,如同Unix中的文件路径。路径必须是绝对的,因此他们必须由斜杠字符来开头。除此以外,他们必须是唯一的,也就是说每一个路径只有一个表示,因此这些路径不能改变。在ZooKeeper中,路径由Unicode字符串组成,并且有一些限制。字符串"/zookeeper"用以保存管理信息,比如关键配额信息
【4.1】 数据结构图
- 图中的每个节点称为一个Znode。 每个Znode由3部分组成:
- ① stat:此为状态信息, 描述该Znode的版本, 权限等信息
- ② data:与该Znode关联的数据
- ③ children:该Znode下的子节点
【4.2】 节点类型
- Znode有两种,分别为
临时节点和永久节点 - 节点的
类型在创建时即被确定,并且不能改变 - 临时节点:该节点的生命周期依赖于创建它们的会话,一旦
会话结束,临时节点将被自动删除,当然可以也可以手动删除;临时节点不允许拥有子节点 - 永久节点:该节点的生命周期不依赖于会话,并且只有在客户端
显示执行删除操作的时候,他们才能被删除 - Znode还有一个
序列化的特性,如果创建的时候指定的话,该Znode的名字后面会自动追加一个不断增加的序列号。序列号对于此节点的父节点来说是唯一的,这样便会记录每个子节点创建的先后顺序。它的格式为“%10d”(10位数字,没有数值的数位用0补充,例如“0000000001”) - 这样便会存在四种类型的Znode节点,分别对应:
-
PERSISTENT:永久节点 -
EPHEMERAL:临时节点 -
PERSISTENT_SEQUENTIAL:永久节点、序列化 -
EPHEMERAL_SEQUENTIAL:临时节点、序列化
-
【4.3】 节点属性
每个znode都包含了一系列的属性,通过命令get,可以获得节点的属性
-
dataVersion:数据版本号,每次对节点进行set操作,dataVersion的值都会增加1(即使设置的是相同的数据),可有效避免了数据更新时出现的先后顺序问题 -
cversion:子节点的版本号。当znode的子节点有变化时,cversion 的值就会增加1 -
cZxid:Znode创建的事务id -
mZxid:Znode被修改的事务id,即每次对znode的修改都会更新mZxid - 对于zk来说,每次的变化都会产生一个
唯一的事务id,zxid(ZooKeeper Transaction Id)。通过zxid,可以确定更新操作的先后顺序。例如,如果zxid1小于zxid2,说明zxid1操作先于zxid2发生,zxid对于整个zk都是唯一的,即使操作的是不同的znode -
ctime:节点创建时的时间戳 -
mtime:节点最新一次更新发生时的时间戳 -
ephemeralOwner:如果该节点为临时节点, ephemeralOwner值表示与该节点绑定的session id. 如果不是, ephemeralOwner值为0 - 在client和server通信之前,首先需要建立连接,该连接称为
session。连接建立后,如果发生连接超时、授权失败,或者显式关闭连接,连接便处于CLOSED状态, 此时session结束
五、ZooKeeper Watcher(监听机制)
简介
- ZooKeeper提供了
分布式数据发布/订阅功能,一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使他们能够做出相应的处理 - ZooKeeper中,引入了
Watcher机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watcher监听,当服务端的一些事件触发了这个Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能 -
触发事件种类很多,如:节点创建,节点删除,节点改变,子节点改变等
总的来说可以概括Watcher为以下三个过程:客户端向服务端注册Watcher、服务端事件发生触发Watcher、客户端回调Watcher得到触发事件情况
【5.1】 Watch机制特点
一次性触发
事件发生触发监听,一个watcher event就会被发送到设置监听的客户端,这种效果是一次性的,后续再次发生同样的事件,不会再次触发
事件封装
ZooKeeper使用WatchedEvent对象来封装服务端事件并传递WatchedEvent包含了每一个事件的三个基本属性:通知状态(keeperState),事件类型(EventType)和节点路径(path)
event异步发送
watcher的通知事件从服务端发送到客户端是异步的
先注册再触发
Zookeeper中的watch机制,必须客户端先去服务端注册监听,这样事件发送才会触发监听,通知给客户端
【5.2】 通知状态和事件类型
同一个事件类型在不同的通知状态中代表的含义有所不同,下表列举了常见的通知状态和事件类型
其中连接状态事件(type=None, path=null)不需要客户端注册,客户端只要有需要直接处理就行了
【5.3】 Shell 客户端设置watcher
设置节点数据变动监听:
通过另一个客户端更改节点数据:
此时设置监听的节点收到通知:
六、ZooKeeper Java API
简介
org.apache.zookeeper.Zookeeper
Zookeeper 是在Java中客户端主类,负责建立与zookeeper集群的会话,并提供方法进行操作
org.apache.zookeeper.Watcher
Watcher接口表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两个枚举类,
分别代表了通知状态和事件类型,同时定义了事件的回调方法:process(WatchedEvent event)
process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,
客户端就会对相应的process方法进行回调,从而实现对事件的处理
基本使用
建立Java maven项目,引入maven pom坐标
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> </dependency>
示例1
public static void main(String[] args) throws Exception { // 初始化 ZooKeeper实例(zk地址、会话超时时间,与系统默认一致、watcher) ZooKeeper zk = new ZooKeeper("node01:2181,node02:2181", 30000, new Watcher() { @Override public void process(WatchedEvent event) { System.out.println("事件类型为:" + event.getType()); System.out.println("事件发生的路径:" + event.getPath()); System.out.println("通知状态为:" +event.getState()); } }); zk.create("/tmp", "HelloWorld".getBytes("UTF-8"), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.close(); }
示例2
public static void main(String[] args) throws Exception { // 初始化 ZooKeeper实例(zk地址、会话超时时间,与系统默认一致、watcher) ZooKeeper zk = new ZooKeeper("node01:2181,node02:2181", 30000, new Watcher() { @Override 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(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // 创建一个子目录节点 zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(), 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(), 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(); }
七、ZooKeeper选举机制
默认算法:
Zookeeper默认的算法是FastLeaderElection,采用投票数大于半数则胜出的逻辑
概念
- 服务器ID
比如有五台服务器,编号分别是1,2,3,4,5
编号越大在选择算法中的权重越大 - 选举状态
LOOKING,竞选状态
FOLLOWING,随从状态,同步leader状态,参与投票
OBSERVING,观察状态,同步leader状态,不参与投票
LEADING,领导者状态 - 数据ID
服务器中存放的最新数据version
值越大说明数据越新,在选举算法中数据越新权重越大 - 逻辑时钟
也叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断
全新集群选举
假设目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:
- 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking
- 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING
- 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为领导者,服务器1,2成为小弟
- 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为小弟
- 服务器5启动,后面的逻辑同服务器4成为小弟
非全新集群选举
对于运行正常的zookeeper集群,中途有机器down掉,需要重新选举时,选举过程就需要加入数据ID、服务器ID和逻辑时钟
- 数据ID:数据新的version就大,数据每次更新都会更新version
- 服务器ID:就是我们配置的myid中的值,每个机器一个
- 逻辑时钟:这个值从0开始递增,每次选举对应一个值。 如果在同一次选举中,这个值是一致的
- 这样选举的标准就变成:
1、逻辑时钟小的选举结果被忽略,重新投票
2、统一逻辑时钟后,数据id大的胜出
3、数据id相同的情况下,服务器id大的胜出
根据这个规则选出leader
4)Hadoop安装
【开篇】HA概述与实现
HDFS 是一个分布式文件系统,有namenode和datanode,我们都知道,
一旦namenode荡机,整个集群就会瘫痪,那么这个问题怎么处理?
一般我们都会有两个namenode,我们知道有一个secondary namenode,但是我们知道这个namenode并不能执行namenode的功能,他只是帮namenode做操作日志的合并,所以我们需要另一种部署模式,即HA部署模式
HA部署模式,是一种高可用部署模式,也就是一天24小时都在工作,他有两个namenode。namenode记录的是元数据,这个元数据放在内存中, 在磁盘上有一个镜像文件,这个镜像文件是fsimage+编号,还有大量的操作日志叫做edits+编号,两个编号都是对应起来的,而且内存里面的元数据都是齐全的,两个namenode只有一个是对客户端服务的,另外一个用来备份,对外服务的状态成为active,备份的是standby,如果有一天active namenode荡机了,standby要接管对外服务,但是它还没有元数据,那么这个问题怎么解决的。
如果active namenode荡机,standby要立马接管,意味着这两个的元数据必须要时刻同步,如果是standby namenode经常性的去active拷贝元数据信息,那么这样对active namenode的压力是很大的,所以首先,一开始格式化的时候,生成一个最初的元数据,先给standby拷贝一份,在运行的过程中,日志不仅在自己的磁盘上,还放在一个 日志存储 系统中,standby定期的去从日志存储系统中拿取日志文件,并且和最初的元数据fsimage进行合并,生成一个新的镜像,如果差下那么一点日志没有合并到,就在这一瞬间,active namenode荡机了,然后standby namenode会从日志存储系统拿取缺少的那一块日志,与原来的元数据进行合并,进行更新,这样状态就和active namenode的状态是一致的,这样就可以很快的接手对外服务。
日志存储系统:
这是个很重要的,这个系统是不能挂掉的,这个系统不是一个单节点,这个系统也是一个集群,里面有很多台机器,这个集群也是基数台,而且每台之间会同步日志,这样一来,日志存储系统的可用性就会很高了,数据同步的算法和zookeeper是一样的,即数据在多个节点之间同步,采用的是paxos算法,多数成立则成立,所以这个日志存储系统最多可以挂掉半数以下的机器,这个系统叫做QJournal,底层的功能依赖zookeeper集群,这两个集群在业务上没关系,只是利用zookeeper,就像hbase依赖zookeeper一样。
但是现在有一个问题,就是active namenode这台机器挂掉之后,standby namenode这台机器是怎么知道的,active namenode 可以在zookeeper上记载东西,然后standby去监听,一旦这个active namenode不见了,那么就说明挂了,这是一种方法。
官方是这么做的,提供了一个额外的程序,叫做zkfc,就是基于zookeeper实现的failover controller,故障控制器,运行在namenode机器上监控namenode的进程并且把监控信息记录在zookeeper中,standby 机器也会运行zkfc,监控自己机器上的进程,也会监听zookeeper里面的另一个zkfc写的东西,一旦发生变化,得到zookeeper的通知,就可以调用方法,将自己的状态从standby切换成active状态,然后开始对外服务,但是问题没有那么简单,有时候JVM会冻结这个namenode,zkfc以为namenode挂掉了,其实只是清理以及维护,但是这样的话,zkfc将将状态提交给zookeeper,然后standby namenode会收到zookeeper的通知,那就切换状态了,这就完了,就将存在两个active namenode,这样系统会错乱。
这里还有一个机制,就是当standby namenode收到通知切换状态的时候,先不着急切换,而是先采取措施确保防止这种系统的紊乱,首先会做两件事。
1.通过SSH远程指令,杀掉active namenode 的进程,但是如果不仅仅是namenode挂了,而是整个机器挂了,那发送的指令
就不会有反应,也不会有反馈信息,
2.那么如果SSH没有响应,则帮用户调用一个用户所指定的脚本,脚本运行成功,则切换状态
做完这两件事,状态就切换成功了,这就是HA高可用集群运行机制。
一、准备工作
1.在四台节点上安装JDK以及Hadoop 2.在node02、node03、node04节点上安装Zookeeper 3.节点配置分布如下