一、Hadoop HA 高可用集群整体架构
在 Hadoop 1.0 时代,Hadoop 中的HDFS 集群中面临一个问题,即NameNode 单点问题,如果在集群运行过程中,NameNode出现故障宕机后,那么整个集群将会面临瘫痪。
Hadoop 2.0 以后,NameNode 的单点问题得到了解决,共有两台NameNode并形成互备,一台处于活动状态,一台处于备用状态,只有活动状态的NameNode才会对外提供服务,而备用状态的NameNode不对外提供服务,仅同步Active NameNode的状态,以便能在它失败时快速进行切换
上图为Hadoop HA 的高可用整体架构图,它的主要主成部分如下
1.两台NameNode
Active NameNode 和 Standby NameNode:两台 NameNode形成互备,一台处于 Active(活动)状态,一台处理Standby(备用)状态,只有主NameNode才能对外提供读写服务
2.主备切换控制器:ZKFailoverController
ZKFailoverController作为独立的进程运行,对NameNode的主备切换进行总体控制,及时监控检测NameNode的健康状态,当主 NameNode发生故障后,借助Zookeeper实现自动的主备选举和切换。
3.Zookeeper集群
为主备切换控制器(ZKFailoverController)提供主备选举支持,当一个NameNode节点出现故障后,切换备用NameNode为主节点,从而实现Hadoop HA 高可用。
4.基于QJM的共享存储系统
QJM为Quorum Journal Manager的缩写,JournalNode中保存了NameNode在运行过程中所产生的HDFS的元数据,主NameNode和备NameNode通过共享存储系统实现元数据同步,在进行主备切换时,新的NameNode在确认元数据完全同步完成后才能继续对外提供服务。
5.DN
DataNode的缩写,用于存放数据文件的节点,hadoop2.x默认一个块的大小为128M,hadoop1.0为64M,默认备份数量为3,可以通过hadoop 的配置文件修改。
NameNode主备切换实现
Hadoop HA 中有两台NameNode,它们之间形成互备,那么我们来看下它是如何实现主备切换
NameNode 主备切换主要由ZKFailoverController、HealthMonitor和ActiveStandbyElector三个组件协同实现
1.ZKFailoverController
作为NameNode上一个独立的进程启动,启动后会创建HealthMonitor和ActiveStandbyElector,创建的同时会注册相应的回调方法。
2.HealthMonitor
主要负责检测NameNode的健康状态,如果检测到NameNode的状态发生变化,则回调ZKFailoverController的相应方法进行自动的主备选举
3.ActiveStandbyElector
主要负责完成自动的主备选举,内部封装了zookeeper的处理逻辑,一旦zookeeper主备选举完成,会回调ZKFailoverController的相应方法进行NameNode的主备状态切换
二、前期准备
编号 |
系统 |
IP |
主机名称 |
node1 |
centos7 |
192.168.18.27 |
master27 |
node2 |
centos7 |
192.168.18.28 |
master28 |
node3 |
centos7 |
192.168.18.29 |
dn29 |
node4 |
centos7 |
192.168.18.30 |
dn30 |
node5 |
centos7 |
192.168.18.31 |
dn31 |
参考如上,创建5台虚拟机,使用最小安装,内存最小1G,创建完成后,分别配置主机名、静态IP、主机名与IP映射、创建 hadoop 用户并为 hadoop 用户授权,配置无密登录两个NN都要无密登录其他的机器上
在进行正式软件安装前我们需要把防火墙和selinux守护进程关闭也可以在集群配置文件完成后启动集群之前操作如下命令:
# systemctl status firewalld # 查看防火墙状态# systemctl stop firewalld # 关闭防火墙# systemctl disable firewalld # 禁止防火墙开机自启动
# getenforce # 查看守护进程状态# setenforce
0
# 临时关闭守护进程# vi /etc/selinux/config 设置SELINUX=disabled # 永久关闭守护进程
三、软件安装
在5台虚拟机中分别安装 jdk 及 hadoop
hadoop ha 配置(node1、2、3、4、5)
node1、node2、node3、node4、node5分别配置
core-site.xml:
fs.defaultFS
hdfs://cluster
hadoop.tmp.dir
/home/hadoop/app/hadoop/tmp
指定hadoop临时目录
ha.zookeeper.quorum
dn29:2181,dn30:2181,dn31:2181
指定zookeeper地址
ha.zookeeper.session-timeout.ms
300000
zk的超时时间,单位为毫秒,默认为5000,这个值比较小。建
议设置得大一些,zk过于敏感,避免因为网路抖动等原因引起NameNode进行无所谓的>主备切换
fs.trash.interval
1440
开启垃圾回收站功能,防止误删除文件,HDFS文件删除后先放
入回收站,单位为分,垃圾回收站最长保留数据时间为1天,超过一天后删除
io.file.buffer.size
131072
设置SequenceFile中用到的读/写缓存大小,合理设置缓存大>小有利于提高数据传输效率,单位为byte,默认为4KB,这里设置为128KB
hdfs-site.xml
dfs.nameservices
cluster
指定hdfs的nameservice为cluster,需要和core-site.xml文件中的保持一致
dfs.ha.namenodes.cluster
master27,master28
cluster下有两个NameNode,分别为node1和node2
dfs.namenode.rpc-address.cluster.node1
master27:9000
NameNode1的RPC通信地址,端口要和core-site.xml中fs.defaultFS的一致
dfs.namenode.http-address.cluster.node1
master27:50070
NameNode1的HTTP通信地址
dfs.namenode.rpc-address.cluster.node2
master28:9000
NameNode2的RPC通信地址,端口要和core-site.xml中fs.defaultFS的一致
dfs.namenode.http-address.cluster.node2
master28:50070
NameNode2的HTTP通信地址
dfs.namenode.shared.edits.dir
qjournal://dn29:8485;dn30:8485;dn31:8485/cluster
指定NameNode的元数据在JournalNode上的存放位置
dfs.journalnode.edits.dir
/home/hadoop/app/hadoop/journaldata
指定NameNode的元数据在JournalNode上的存放位置
dfs.ha.automatic-failover.enabled
true
指定支持高可用自动切换机制
dfs.client.failover.proxy.provider.cluster
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
配置失败自动切换实现方式
dfs.ha.fencing.methods
sshfence
shell(/bin/true)
配置隔离机制,主要用于远程管理监听其他机器相关服务
dfs.ha.fencing.ssh.private-key-files
/home/hadoop/.ssh/id_rsa
使用隔离机制时需要ssh免密码登陆,/home/hadoop/为用户目录
dfs.ha.fencing.ssh.connect-timeout
30000
使用隔离机制时需要ssh免密码登陆时的超时时间,单位为毫秒
dfs.namenode.name.dir
file:/home/hadoop/app/hadoop/tmp/name
NameNode结点存储hadoop文件系统信息的本地系统路径
dfs.datanode.data.dir
file:/home/hadoop/app/hadoop/tmp/data
DataNode结点被指定要存储数据的本地文件系统路径,这个值只对NameNode有效,DataNode并不需要使用到它
dfs.webhdfs.enabled
true
指定可以通过web访问hdfs目录
mapred-site.xml
mapreduce.framework.name
yarn
yarn-site.xml
yarn.log-aggregation-enable
true
开启日志聚合功能,默认为false
yarn.log-aggregation.retain-seconds
259200
在HDFS上聚合的日志最长保留多少秒,这里配置为3天
yarn.resourcemanager.ha.enabled
true
开启resourcemanager ha,默认为false
yarn.resourcemanager.cluster-id
yrc
yarn.resourcemanager.ha.rm-ids
rm1,rm2
yarn.resourcemanager.hostname.rm1
master27
yarn.resourcemanager.hostname.rm2
master28
yarn.resourcemanager.zk-address
dn29:2181,dn30:2181,dn31:2181
yarn.nodemanager.aux-services
mapreduce_shuffle
yarn.nodemanager.aux-services.mapreduce.shuffle.class
org.apache.hadoop.mapred.ShuffleHandler
slaves
dn29
dn30
dn31
安装zookeeper(node3、node4、node5)
分别在node3、4、5中安装 zookeeper
zookeeper 官网下载地址博主这里的版本是3.4.10
jdk、hadoop、zookeeper环境变量如下,配置在 ~/.bashrc 文件中(用户变量)
jdk
export JAVA_HOME=/home/hadoop/app/jdk
# Hadoop
export HADOOP_HOME=/home/hadoop/app/hadoop
export HADOOP_INSTALL=$HADOOP_HOME
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin
# Zookeeper
export ZOOKEEPER_HOME=/home/hadoop/app/zookeeper
# PATH
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/sbin:$HADOOP_HOME/bin:$ZOOKEEPER_HOME/bin
四、集群配置(zookeeper、hadoop)
1.zookeeper 配置(node3、4、5)
在 node3、node4、node5 中的 zookeeper 安装目录下分别创建一个文件data(mkdir data 用于存放数据),作为 zookeeper 的 数据文件,并在data目录下创建一个文件 myid (touch myid)且在文件中写入一个数字(在myid中分别加入1、2、3对应node3、node4、node5依次加入)
在 zookeeper 安装目录下的 conf 目录下有一个名为 zoo_sample.cfg 的文件,拷贝该文件命名为zoo.cfg,我们需要配置该文件,zookeeper 在启动时会找这个文件作为默认配置文件。执行如下命令
cp zoo_sample.cfg zoo.cfg
编辑zoo.cfg
修改:dataDir=/home/hadoop/app/zookeeper/data
在最下面添加:
# 配置zookeeper集群的主机和ip,1 2 3 表示zookeeper服务的编号
server.1=dn29:2888:3888
server.2=dn30:2888:3888
server.3=dn31:2888:3888
五、集群启动关闭
1.手动启动关闭集群
集群启动
1).启动zookeeper(node3、node4、node5)
.启动:zkServer.sh start 关闭:
zkServer.sh stop
显示Starting zookeeper ... STARTED为启动成功
2).启动journalnode(node3、node4、node5)
hadoop-daemon.sh start journalnode
3).格式化HDFS(node1)
注意:格式化后需要把tmp目录拷贝给node2,不然node2的namenode启动不起来,
第一次启动时需要格式化
hdfs namenode -format
scp -r /home/hadoop/app/hadoop/tmp hadoop@master26:/home/hadoop/app/hadoop/
4).格式化ZKFC(node1)
注意:
第一次启动时需要格式化
hdfs zkfc -formatZK
5).启动HDFS(node1)
启动:
sh start-dfs.sh 关闭:sh stop-dfs.sh
6).启动YARN(node1)
启动:
sh
start-yarn.sh 关闭:sh stop-yarn.sh
7).启动resourcemanager(node2)
node2的resourcemanager需要手动单独启动
启动:sh
yarn-daemon.sh start resourcemanager
关闭:
sh
yarn-daemon.sh stop resourcemanager
8).查看进程
$
jps
# 如果集群启动后看到的进程和下面一样表示成功,否则失败
node1、node2
NameNode、DFSZKFailoverController、ResourceManager
node3、node4、node5
DataNode、NodeManager、JournalNode、QuorumPeerMain
2.集群启动关闭 shell 脚本
每次手动开启或关闭集群,即繁琐又不方便,所以笔者写了一个脚本,通过脚本来管理集群的启动和关闭
zookeeper 集群管理脚本
#!/bin/bash
# FileName:zk-manage.sh
# Description:zookeeper 集群启动关闭管理脚本
# Author:david
SLAVES=$(cat /usr/local/hadoop/etc/hadoop/slaves)
#echo $SLAVES
start_time=`date +%s`
for
slave
in
$SLAVES
do
case
$1
in
start) ssh -t
$slave
"zkServer.sh start"
1
>/dev/null;; stop) ssh -t
$slave
"zkServer.sh stop"
1
>/dev/null;; status)
echo
&& ssh -t
$slave
"zkServer.sh status"
;; restart) ssh -t
$slave
"zkServer.sh restart"
1
>/dev/null;; *)
echo
-e
"Usage:sh zk-manage.sh {start|stop|status|restart} ^_^\n"
&&
exit
;;
esac
done
end_time=`date +%s`elapse_time=$((
${end_time}
-
${start_time}
))
echo
-e
"\n$1 ZooKeeper Server takes ${elapse_time} seconds\n"
hadoop 管理脚本
#!/bin/bash
# FileName:hadoop-manage.sh
# Description:hadoop 启动关闭管理脚本,hdfs、yarn及node2上的resourcemanager需要单独启动
# Author:david
NameNode1=node1NameNode2=node2start_time=`date +%s`
case
$1
in
start) ssh -t
$NameNode1
"start-dfs.sh"
ssh -t
$NameNode1
"start-yarn.sh"
ssh -t
$NameNode2
"yarn-daemon.sh start resourcemanager"
;; stop) ssh -t
$NameNode1
"stop-dfs.sh"
ssh -t
$NameNode1
"stop-yarn.sh"
ssh -t
$NameNode2
"yarn-daemon.sh stop resourcemanager"
;; *)
echo
-e
"Usage: hadoop-manage.sh {start|stop} ^_^\n"
&&
exit
;;
esac
end_time=`date +%s`elapse_time=$((
${end_time}
-
${start_time}
))
echo
-e
"\n$1 Hadoop Server takes ${elapse_time} seconds\n"
hadoop ha 集群管理脚本
#!/bin/bash
# FileName:hadoop-ha-cluster.sh
# Description:hadoop ha 高可用集群启动关闭脚本
# Author:david
#CLUSTER_CONF_PATH=$(cd "$(dirname "$0")"; pwd)
NameNode1=node1NameNode2=node2DataNode1=node3DataNode2=node4DataNode3=node5start_time=`date +%s`
# 查看状态函数封装
function
showJps
(){
# 查看namenode1(node1)的进程
echo
-e
"\n**********************************************************************************"
ssh -t
$NameNode1
<< n1
echo
"当前 $NameNode1 上的进程为: "
jps
exit
n1
# 查看namenode2(node2)的进程
echo
-e
"\n**********************************************************************************"
ssh -t
$NameNode2
<< n2
echo
"当前 $NameNode2 上的进程为: "
jps
exit
n2
# 查看datanode1(node3)的进程
echo
-e
"\n**********************************************************************************"
ssh -t
$DataNode1
<< d1
echo
"当前 $DataNode1 上的进程为: "
jps
exit
d1
# 查看datanode2(node4)的进程
echo
-e
"\n**********************************************************************************"
ssh -t
$DataNode2
<< d2
echo
"当前 $DataNode2 上的进程为: "
jps
exit
d2
# 查看datanode3(node5)的进程
echo
-e
"\n**********************************************************************************"
ssh -t
$DataNode3
<< d3
echo
"当前 $DataNode3 上的进程为: "
jps
exit
d3}
case
$1
in
# 先启动zk,再启动hadoop
start) sh zk-manage.sh start sh hadoop-manage.sh start ;;
# 先关闭hadoop,在关闭zk
stop) sh hadoop-manage.sh stop sh zk-manage.sh stop ;;
# 先关闭hadoop,在重启zk,在启动hadoop
restart) sh hadoop-manage.sh stop sh zk-manage.sh restart sh hadoop-manage.sh start ;;
# 显示进程
status) showJps ;; *)
echo
-e
"Usage: sh hadoop-ha-cluster.sh {start|stop|restart|status} ^_^\n"
;;
esac
end_time=`date +%s`elapse_time=$((
${end_time}
-
${start_time}
))
echo
-e
"\n$1 Hadoop HA Cluster Server takes ${elapse_time} seconds\n"
将上面三个脚本分别存放在一个单独文件中,并存放在同一目录下,使用如下命令管理 hadoop ha 高可用集群的启动、关闭、重启、查看进程。
sh hadoop-ha-cluster
.sh
start
# 启动集群
sh hadoop-ha-cluster
.sh
stop
# 关闭集群
sh hadoop-ha-cluster
.sh
restart
# 重启集群
sh hadoop-ha-cluster
.sh
status
# 查看每个节点上的进程