Hadoop高可用(Hadoop2.x)
目录
1.什么是高可用
高可用性HA(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性
2.Hadoop集群存在的问题
- HDFS的单点故障,NameNode单点故障,难以应用于在线场景
- 单个NameNode压力过大,且内存受限,影响系统扩展性
- Yarn的单点故障,Resourcemanager单点故障,导致MR程序无法正常运行
3.单点故障
单点故障(single point of failure,缩写SPOF)是指系统中一点失效,就会让整个系统无法运作的部件,换句话说,单点故障即会整体故障。
3.1HDFS的单点故障
在Hadoop 2.0之前,NameNode是HDFS集群中的单点故障(SPOF)。每个群集只有一个NameNode,如果该计算机或进程不可用,则整个群集将不可用,直到NameNode重新启动或在单独的计算机上启动
3.2NameNode的内存受限的问题
单个NameNode节点的机器的内存是有限的,随着对HDFS文件系统的操作次数的增多,产生的日志文件(edits.log)和元数据的序列化文件(FsImage)会不断的增大,最终元数据文件会读到内存之中,而内存是有限,这样就会导致HDFS的启动速度变慢,也不利于集群DataNode的扩展。
3.3Yarn的单点故障
Hadoop2.0引入的统一的资源调度平台Yarn,包含一个Resourcemanger和多个NodeManager,Resourcemanger很重要的一个功能就是负责处理客户端提交的MR程序,并将该程序启动。如果Resourcemanger发生单点故障,就会导致MR程序无法在Yarn运行。
4.Hadoop的高可用
Hadoop实现高可用主要有两种方式,一种是使用共享日志编辑系统(QJM),另一种是基于网络文件系统(NFS)的高可用方案。基于NFS的高可用方案需要额外安装NFS服务器,而QJM的高可用方案不需要安装额外的服务器。两种高可用方案都依赖于Zookeeper。
两个单独的计算机配置为NameNode。在任何时间点,一个NameNode都恰好处于活动状态(Active),而另一个则处于Standby状态。Active NameNode负责集群中的所有客户端操作,而Standby则仅充当从属,并保持足够的状态以在必要时提供快速故障转移。基于JournalNode实现的高可用,如下图:
1.两台NN启动后都会去zk(zookeeper)进行注册,优先注册的为主节点(Active),另外一个为备节点(Standby),
2.主NN对外提供服务,备NN同步主NN元数据,以待切换,通过集群JN(JournalNode)。
备用NN也会帮助主NN合并editsLog文件和fsimage产生新的fsimage,并推送ActiveNN。
3.ZKFailover Controller(ZKFC,与NN在同一机器上)的作用是监控NameNode健康状态,当主NN挂掉之后,备用NN的ZKFC会得到消息,然后会将备用NN状态改为(Active),并是原来的主NN改为备用NN。
4.DN(datenode)会同时把信息报告给主从NN。
以上都是主备NN自动切换,基于zookeeper实现;
手动切换:通过命令实现,场景—HDFS升级等场合
5. Hadoop HA架构搭建
使用VmWare模拟多台机器,由于电脑配置有限,只使用三台机器,配置如下:
主机名 |
IP |
内存 |
磁盘 |
node-1 |
192.168.200.10 |
2G |
40G |
node-2 |
192.168.200.20 |
2G |
40G |
node-3 |
192.168.200.30 |
2G |
40G |
集群的节点角色分配如下:
5.1基本环境配置
在三台机器上做如下操作
1.关闭防火墙
2.配置/etc/hosts
3.配置时间同步
4.配置ssh免密码登录(三台机器都要配置)
5.安装JDK并配置环境变量
5.2安装Zookeeper
需要上传zookeeper的安装包
5.2.1解压安装包
tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/ |
5.2.2配置环境变量
vi /etc/profile |
export ZOOKEEPER_HOME=/opt/zookeeper-3.4.10/ export PATH=$PATH:$ZOOKEEPER_HOME/bin |
source /etc/profile |
5.2.3修改配置文件
配置文件位于zookeeper安装目录的conf目录
cd /opt/zookeeper-3.4.10/conf/ 复制配置文件模板 cp zoo_sample.cfg zoo.cfg vi zoo.cfg dataDir=/opt/zookeeper-3.4.10/zkdata server.1=node-1:2888:3888 server.2=node-2:2888:3888 server.3=node-3:2888:3888 |
PS:2888为集群之间通信的端口,主要由leader管理,3888是leader选举时使用的端口,2181为客户端提供服务的端口
5.2.4创建存放数据的文件夹
mkdir /opt/zookeeper-3.4.10/zkdata |
5.2.5分发安装包到其他节点
scp -r /opt/zookeeper-3.4.10 node-1:/opt/ scp -r /opt/zookeeper-3.4.10 node-2:/opt |
4.2.6myid文件
集群中的每台ZK server都会有一个用于唯一标识自己的id,有两个地方会使用到这个id:myid文件和zoo.cfg文件中。myid文件存储在dataDir目录中,指定了当前server的server id。在zoo.cfg文件中,根据server id,配置了每个server的ip和相应端口。Zookeeper启动的时候,读取myid文件中的server id,然后去zoo.cfg 中查找对应的配置
node-1 echo 1 > /opt/zookeeper-3.4.10/zkdata/myid |
node-2 echo 2 > /opt/zookeeper-3.4.10/zkdata/myid |
node-3 echo 3 > /opt/zookeeper-3.4.10/zkdata/myid |
5.3安装Hadoop
使用 sftp 将 Hadoop 的安装包上传到node-1
1.解压
2.配置环境变量
3.修改配置文件
- hadoop-env.sh
export JAVA_HOME=/opt/jdk1.8.0_171 |
- core-site.xml
<!-- 指定hdfs的nameservice为hadoop-ha --> <property> <name>fs.defaultFS</name> <value>hdfs://hadoop-ha/</value> </property> <!-- 指定hadoop临时目录 --> <property> <name>hadoop.tmp.dir</name> <value>/opt/hdfs</value> </property> <!-- 指定zookeeper地址 --> <property> <name>ha.zookeeper.quorum</name> <value>node-1,node-2,node-3</value> </property> |
- hdfs-site.xml
<!--指定hdfs的nameservice为hadoop-ha,需要和core-site.xml中的保持一致 --> <property> <name>dfs.nameservices</name> <value>hadoop-ha</value> </property> <!-- hadoop-ha下面有两个NameNode,分别是nn1,nn2 --> <property> <name>dfs.ha.namenodes.hadoop-ha</name> <value>nn1,nn2</value> </property> <!-- nn1的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.hadoop-ha.nn1</name> <value>node-1:9000</value> </property> <!-- nn1的http通信地址 --> <property> <name>dfs.namenode.http-address.hadoop-ha.nn1</name> <value>node-1:50070</value> </property> <!-- nn2的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.hadoop-ha.nn2</name> <value>node-2:9000</value> </property> <!-- nn2的http通信地址 --> <property> <name>dfs.namenode.http-address.hadoop-ha.nn2</name> <value>node-2:50070</value> </property> <!-- 指定NameNode的edits元数据在机器本地磁盘的存放位置 --> <property> <name>dfs.namenode.name.dir</name> <value>/opt/hdfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/opt/hdfs/data</value> </property> <!-- 指定NameNode的共享edits元数据在JournalNode上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://node-1:8485;node-2:8485;node-3:8485/hadoop-ha</value> </property> <!-- 指定JournalNode在本地磁盘存放数据的位置 --> <property> <name>dfs.journalnode.edits.dir</name> <value>/opt/hdfs/journaldata</value> </property> <!-- 开启NameNode失败自动切换 --> <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property> <!-- 配置失败自动切换实现方式 --> <property> <name>dfs.client.failover.proxy.provider.hadoop-ha</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> <!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行--> <property> <name>dfs.ha.fencing.methods</name> <value> sshfence shell(/bin/true) </value> </property> <!-- 使用sshfence隔离机制时需要ssh免登陆 --> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/root/.ssh/id_rsa</value> </property> <!-- 配置sshfence隔离机制超时时间 --> <property> <name>dfs.ha.fencing.ssh.connect-timeout</name> <value>30000</value> </property> |
- mapred-site.xml
<!-- 指定mr框架为yarn方式 --> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> |
- yarn-site.xml
<property> <!-- 开启yarn的高可用 --> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property> <!-- 指定高可用集群的名称 --> <property> <name>yarn.resourcemanager.cluster-id</name> <value>yrc</value> </property> <!-- 指定resourcemanager的名称 --> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property> <!-- 指定rm1的主机 --> <property> <name>yarn.resourcemanager.hostname.rm1</name> <value>node-1</value> </property> <!-- 指定rm2的主机 --> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>node-3</value> </property> <!-- 指定zookeeper的地址 --> <property> <name>yarn.resourcemanager.zk-address</name> <value>node-1:2181,node-2:2181,node-3:2181</value> </property> <!-- 指定mapreduce的shuffle机制 --> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <!-- 指定rm1的rpc通信地址 --> <property> <name>yarn.resourcemanager.address.rm1</name> <value>node-1:8032</value> </property> <!-- 指定rm1的任务调度的地址 --> <property> <name>yarn.resourcemanager.scheduler.address.rm1</name> <value>node-1:8030</value> </property> <!-- 指定rm1的web界面的地址 --> <property> <name>yarn.resourcemanager.webapp.address.rm1</name> <value>node-1:8088</value> </property> <!-- 指定rm1的任务资源跟踪的地址 --> <property> <name>yarn.resourcemanager.resource-tracker.address.rm1</name> <value>node-1:8031</value> </property> <!-- 指定rm1的管理地址 --> <property> <name>yarn.resourcemanager.admin.address.rm1</name> <value>node-1:8033</value> </property> <!-- 指定rm1的高可用的管理地址 --> <property> <name>yarn.resourcemanager.ha.admin.address.rm1</name> <value>node-1:23142</value> </property> <!-- 指定rm2的rpc通信地址 --> <property> <name>yarn.resourcemanager.address.rm2</name> <value>node-3:8032</value> </property> <!-- 指定rm2的任务调度的地址 --> <property> <name>yarn.resourcemanager.scheduler.address.rm2</name> <value>node-3:8030</value> </property> <!-- 指定rm2的web界面的地址 --> <property> <name>yarn.resourcemanager.webapp.address.rm2</name> <value>node-3:8088</value> </property> <!-- 指定rm2的任务资源跟踪的地址 --> <property> <name>yarn.resourcemanager.resource-tracker.address.rm2</name> <value>node-3:8031</value> </property> <!-- 指定rm2的管理地址 --> <property> <name>yarn.resourcemanager.admin.address.rm2</name> <value>node-3:8033</value> </property> <!-- 指定rm2的高可用的管理地址 --> <property> <name>yarn.resourcemanager.ha.admin.address.rm2</name> <value>node-3:23142</value> </property> |
- slaves
node-1 node-2 node-3 |
4.分发安装包
scp -r /opt/hadoop-2.9.0 node-2:/opt scp -r /opt/hadoop-2.9.0 node-3:/opt |
5.启动步骤
高可用的启动和普通的启动方式有很大的区别,一定要按照下面的步骤启动
5.1启动zookeeper集群(三台机器)
zkServer.sh start |
5.2手动启动journalnode(三台机器)
hadoop-daemon.sh start journalnode |
启动完成后使用jps命令查看进程
5.3格式化Namenode(node-1)
在node-1节点格式化Hadoop集群
hdfs namenode -format |
格式化完成后,会在hdfs-site.xml中指定的namenode的元数据存放目录生成对应的元数据文件,需要将元数据文件复制到第二个NameNode的机器的对应目录
scp -r /opt/hdfs/name node-2:/opt/hdfs |
5.4格式化ZKFC(node-1)
hdfs zkfc -formatZK |
5.5启动集群
在node-1上执行如下命令
start-dfs.sh start-yarn.sh |
分别访问http://192.168.200.10:50070 http://192.168.200.20:50070可以看到一个NameNode是active的状态另一个NameNode是standby的状态
5.6启动另一个ResourceManager
Yran的ResourceManager需要手动启动另一个,根据yarn-site.xml的配置,在node-3节点上启动ResourceManager
yarn-daemon.sh start resourcemanager |
5.4测试
1.NameNode的高可用测试
查看NameNode的状态,将active状态的NameNode杀掉,一般会根据启动的顺序决定NameNode的状态,使用kill命令杀掉NameNode进程
使用jps查看进程号 kill -9 (NameNode pid) |
可以通过如下命令查看ResourceManager的状态 hdfs haadmin -getServiceState nn1 hdfs haadmin -getServiceState nn2 |
2.ResourceManager的高可用测试
在访问ResourceManage的时候,如果是standby状态的ReSourcemanage会将链接重定向到active的ResourceManager
可以通过如下命令查看ResourceManager的状态
yarn rmadmin -getServiceState rm1 yarn rmadmin -getServiceState rm1 |
6.NameNode的联邦机制
通过多个namenode/namespace把元数据的存储和管理分散到多个节点中,使得namenode/namespace可以通过增加机器来进行水平扩展。
能把单个namenode的负载分散到多个节点中,在HDFS数据规模较大的时候不会也降低HDFS的性能。可以通过多个namespace来隔离不同类型的应用,把不同类型应用的HDFS元数据的存储和管理分派到不同的namenode中。
注意:在Hadoop2.x中联邦只支持两个NameNode,在Hadoop3.x中可以支持多个NameNode
联邦的好处
- 命名空间可伸缩性-联合会添加命名空间水平伸缩。大型部署或使用大量小文件的部署可通过允许将更多的Namenode添加到群集中而受益于命名空间扩展。
- 性能-文件系统的吞吐量不受单个Namenode的限制。向群集添加更多Namenodes可以扩展文件系统的读/写吞吐量。
- 隔离-单个Namenode在多用户环境中不提供隔离。例如,一个实验性应用程序可能会使Namenode过载,并降低生产关键型应用程序的速度。通过使用多个Namenode,可以将不同类别的应用程序和用户隔离到不同的名称空间。