Hadoop HA高可用详细用法

一 Hadoop HA 概述

1)所谓HA(High Availablity),即高可用(7*24小时不中断服务)。

2)实现高可用最关键的策略是消除单点故障。HA严格来说应该分成各个组件的HA机制:HDFS的HA和YARN的HA。

3)Hadoop2.0之前,在HDFS集群中NameNode存在单点故障SPOF(Single Points Of Failure)。

4)NameNode主要在以下两个方面影响HDFS集群

   NameNode机器发生意外,如宕机,集群将无法使用,直到管理员重启

   NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用

HDFS HA功能通过配置Active/Standby两个NameNodes实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器。

1 、HDFS HA

HDFS HA通过多个NameNode来消除单点故障

(1)手动故障转移

1.元数据管理方式需要改变

          内存中各自保存一份元数据;

          Edits日志只有Active状态的NameNode节点可以做写操作;

          两个NameNode都可以读取Edits;

          共享的Edits放在一个共享存储中管理(qjournal和NFS两个主流实现)

   2.必须保证多NameNode之间能够ssh无密码登录

   3.隔离(Fence),即同一时刻仅仅有一个NameNode对外提供服务

以下以三台主机节点hadoop102,hadoop103,hadoop104为例:

主要的配置如下:
在core-site.xml中

<configuration>
<!--把多个NameNode的地址组装成一个集群mycluster -->
     <property>

         <name>fs.defaultFS</name>

          <value>hdfs://mycluster</value>

     </property>
  <!-- 指定hadoop运行时产生文件的存储目录 -->

     <property>

         <name>hadoop.tmp.dir</name>

         <value>/opt/module/ha/hadoop-3.1.3/data/tmp</value>

     </property>

   <!-- 声明journalnode服务器存储目录-->

  <property>

     <name>dfs.journalnode.edits.dir</name>

     <value>file://${hadoop.tmp.dir}/jn</value>

  </property>

</configuration>

配置hdfs-site.xml

<configuration>

  <!-- 完全分布式集群名称 -->

  <property>

     <name>dfs.nameservices</name>

     <value>mycluster</value>

  </property>

  <!--NameNode数据存储目录 -->

  <property>

    <name>dfs.namenode.name.dir</name>

    <value>file://${hadoop.tmp.dir}/name</value>

  </property>
 <!-- DataNode数据存储目录 -->
  <property>

    <name>dfs.datanode.data.dir</name>

    <value>file://${hadoop.tmp.dir}/data</value>

  </property> 

  <!-- 集群中NameNode节点都有哪些 -->

  <property>

     <name>dfs.ha.namenodes.mycluster</name>

     <value>nn1,nn2,nn3</value>

  </property>

  <!-- nn1的RPC通信地址 -->

  <property>

     <name>dfs.namenode.rpc-address.mycluster.nn1</name>

     <value>hadoop102:9000</value>

  </property> 

  <!-- nn2的RPC通信地址 -->

  <property>

     <name>dfs.namenode.rpc-address.mycluster.nn2</name>

     <value>hadoop103:9000</value>

  </property>

  <!-- nn3的RPC通信地址 -->

  <property>

     <name>dfs.namenode.rpc-address.mycluster.nn3</name>

     <value>hadoop104:9000</value>

  </property>


  <!-- nn1的http通信地址 -->

  <property>

     <name>dfs.namenode.http-address.mycluster.nn1</name>

     <value>hadoop102:9870</value>

  </property>
 

  <!-- nn2的http通信地址 -->

  <property>

     <name>dfs.namenode.http-address.mycluster.nn2</name>

     <value>hadoop103:9870</value>

  </property>

  <!-- nn3的http通信地址 -->

  <property>

     <name>dfs.namenode.http-address.mycluster.nn3</name>

     <value>hadoop104:9870</value>

  </property>

 

  <!-- 指定NameNode元数据在JournalNode上的存放位置 -->

  <property>

     <name>dfs.namenode.shared.edits.dir</name>

  <value>qjournal://hadoop102:8485;hadoop103:8485;hadoop104:8485/mycluster</value>

  </property>

 

  <!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->

  <property>

     <name>dfs.ha.fencing.methods</name>

     <value>sshfence</value>

  </property>

 

  <!-- 使用隔离机制时需要ssh无秘钥登录-->

  <property>

     <name>dfs.ha.fencing.ssh.private-key-files</name>

     <value>/home/atguigu/.ssh/id_rsa</value>

  </property>

 

  <!-- 访问代理类:client用于确定哪个NameNode为Active -->

  <property>    <name>dfs.client.failover.proxy.provider.mycluster</name>

 <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>

  </property>

</configuration>

启动HDFS HA集群
①保证Hadoop的环境变量,指向HA集群;
②将hadoop102,hadoop103,hadoop104 节点上/tmp目录下的内容删除
③在各个节点启动journalnode

hdfs --daemon start journalnode

④在nn1节点上,对namenode进行格式化,并启动

hdfs namenode -format

hdfs --daemon start namenode

⑤在nn2,nn3上,同步nn1的元数据信息

hdfs namenode -bootstrapStandby

⑥启动nn2,nn3节点上namenode

hdfs --daemon start namenode

⑦此时,三个节点的namenode均为standby的状态,可以将nn1节点切换为Active

hdfs haadmin -transitionToActive nn1

⑧查看nn1的状态

hdfs haadmin -getServiceState nn1

此时可以将nn1节点的namenode进程杀死,查看nn2,与nn3的namenode的状态,发现当把nn2节点手动设置为Active状态时,并不能成功,因为nn2节点为了防止脑裂的情况,需要连接nn1节点,此时nn1的namenode已经处于dead,所以并不能成功。当重新启动nn1的namenode以后,才能将nn2节点切换为Active,手动切换的状态受限很大。

自动故障转移

前面学习了使用命令hdfs haadmin手动进行故障转移,在该模式下,即使现役NameNode已经失效,系统也不会自动从现役NameNode转移到待机NameNode,下面学习如何配置部署HA自动进行故障转移。自动故障转移为HDFS部署增加了两个新组件:ZooKeeper和ZKFailoverController(ZKFC)进程。ZooKeeper是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。HA的自动故障转移依赖于ZooKeeper的以下功能:

1)故障检测:集群中的每个NameNode在ZooKeeper中维护了一个持久会话,如果机器崩溃,ZooKeeper中的会话将终止,ZooKeeper通知另一个NameNode需要触发故障转移。

2)现役NameNode选择:ZooKeeper提供了一个简单的机制用于唯一的选择一个节点为active状态。如果目前现役NameNode崩溃,另一个节点可能从ZooKeeper获得特殊的排外锁以表明它应该成为现役NameNode。

ZKFC是自动故障转移中的另一个新组件,是ZooKeeper的客户端,也监视和管理NameNode的状态。每个运行NameNode的主机也运行了一个ZKFC进程,ZKFC负责:

1)健康监测:ZKFC使用一个健康检查命令定期地ping与之在相同主机的NameNode,只要该NameNode及时地回复健康状态,ZKFC认为该节点是健康的。如果该节点崩溃,冻结或进入不健康状态,健康监测器标识该节点为非健康的。

2)ZooKeeper会话管理:当本地NameNode是健康的,ZKFC保持一个在ZooKeeper中打开的会话。如果本地NameNode处于active状态,ZKFC也保持一个特殊的znode锁,该锁使用了ZooKeeper对短暂节点的支持,如果会话终止,锁节点将自动删除。

3)基于ZooKeeper的选择:如果本地NameNode是健康的,且ZKFC发现没有其它的节点当前持有znode锁,它将为自己获取该锁。如果成功,则它已经赢得了选择,并负责运行故障转移进程以使它的本地NameNode为Active。故障转移进程与前面描述的手动故障转移相似,首先如果必要保护之前的现役NameNode,然后本地NameNode转换为Active状态。
Hadoop HA高可用详细用法_第1张图片
ZKFC会时刻监视namenode的状态,当ZKFC检测到那么浓的出现异常,将会通知其他的ZKFC2,ZKFC2为了防止脑裂情况的出现,将会强行kill -9 杀死出现异常namenode,然后激活本台的namenode为Active状态。
规划集群配置如下表:
Hadoop HA高可用详细用法_第2张图片

相关的配置如下:
在hdfs-site.xml中增加(开启自动故障转移):

<property>
  <name>dfs.ha.automatic-failover.enabled</name>
  <value>true</value>
</property>

在core-site.xml文件中增加(指定ZK集群的位置)

<property>
  <name>ha.zookeeper.quorum</name>
  <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
</property>

集群的启动
①首先启动zookeeper

zkServer.sh start

②初始化HA在Zookeeper中状态:

hdfs zkfc -formatZK

③启动hdfs

start-dfs.sh

此时查看nn1,nn2,nn3中,namenode的状态,此时谁先抢到谁为Active的状态,假设为nn1–Active,将nn1中的namenode的进程杀死后,nn2,nn3将会自动抢占Active。

2、YARN HA

Hadoop HA高可用详细用法_第3张图片
具体配置:
yarn-site.xml中:

<configuration>
    <property>
    
           <name>yarn.nodemanager.aux-services</name>       
           <value>mapreduce_shuffle</value>
    </property>
    <!--启用resourcemanager ha-->
    <property>
     
        <name>yarn.resourcemanager.ha.enabled</name>
        <value>true</value>
    </property>



    <!--声明HA resourcemanager的地址-->

    <property>

       
        <name>yarn.resourcemanager.cluster-id</name>

        <value>cluster-yarn1</value>

    </property>

     <!-- 指定RM的逻辑列表 -->

    <property>


        <name>yarn.resourcemanager.ha.rm-ids</name>

        <value>rm1,rm2,rm3</value>

    </property>

 

<!-- 指定rm1 的主机名 -->

   
<property>

       
<name>yarn.resourcemanager.hostname.rm1</name>

       
<value>hadoop102</value>

   
</property>

    <!-- 指定rm1的web端地址 -->

<property>

       
<name>yarn.resourcemanager.webapp.address.rm1</name>

       
<value>hadoop102:8088</value>

</property>

   <!-- =========== rm1 配置============  --> 

   <!-- 指定rm1的内部通信地址 -->

   
<property>

       
<name>yarn.resourcemanager.address.rm1</name>

       
<value>hadoop102:8032</value>

   
</property>

  <!-- 指定AM向rm1申请资源的地址 -->

   
<property>

       
<name>yarn.resourcemanager.scheduler.address.rm1</name>  

       
<value>hadoop102:8030</value>

   
</property>

  <!-- 指定供NM连接的地址 --> 


<property>

       
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>

       
<value>hadoop102:8031</value>

</property>

 

<!-- 
=========== rm2 配置============  --> 

 

    <property>

       
<name>yarn.resourcemanager.hostname.rm2</name>

        <value>hadoop103</value>

</property>

 

<property>

       
<name>yarn.resourcemanager.webapp.address.rm2</name>

       
<value>hadoop103:8088</value>

</property>

   
<property>

       
<name>yarn.resourcemanager.address.rm2</name>

       
<value>hadoop103:8032</value>

   
</property>

   
<property>

       
<name>yarn.resourcemanager.scheduler.address.rm2</name>

       
<value>hadoop103:8030</value>

    </property>

 

<property>

       
<name>yarn.resourcemanager.resource-tracker.address.rm2</name>

       
<value>hadoop103:8031</value>

</property>

 

<!-- =========== rm3 配置============  -->  
    <property>

       
         <name>yarn.resourcemanager.hostname.rm3</name>

         <value>hadoop104</value>

    </property>
 
<property>
       
<name>yarn.resourcemanager.webapp.address.rm3</name>       
<value>hadoop104:8088</value>

</property>
   
<property>

       
        <name>yarn.resourcemanager.address.rm3</name>

        <value>hadoop104:8032</value>

   
</property>

   
<property>

       
<name>yarn.resourcemanager.scheduler.address.rm3</name>

       
<value>hadoop104:8030</value>

   
</property>

 

<property>

       
<name>yarn.resourcemanager.resource-tracker.address.rm3</name>

       
<value>hadoop104:8031</value>

</property>

 

    <!--指定zookeeper集群的地址--> 

    <property>

       
<name>yarn.resourcemanager.zk-address</name>

       
<value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>

    </property>

 

    <!--启用自动恢复--> 

    <property>

       
<name>yarn.resourcemanager.recovery.enabled</name>

        <value>true</value>

    </property>

 

    <!--指定resourcemanager的状态信息存储在zookeeper集群--> 

    <property>

       
<name>yarn.resourcemanager.store.class</name>     <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>

</property>

 

<!--环境变量的继承 -->

  <property>

       
<name>yarn.nodemanager.env-whitelist</name>

       
<value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>

    </property>

 

</configuration>

将此配置同步至其他节点。
启动yarn HA
①启动yarn

start-yarn.sh

②查看服务状态

yarn rmadmin -getServiceState rm1

3、HDFS Federation架构设计

  1. NameNode架构的局限性

(1)Namespace(命名空间)的限制

由于NameNode在内存中存储所有的元数据(metadata),因此单个NameNode所能存储的对象(文件+块)数目受到NameNode所在JVM的heap size的限制。50G的heap能够存储20亿(200million)个对象,这20亿个对象支持4000个DataNode,12PB的存储(假设文件平均大小为40MB)。随着数据的飞速增长,存储的需求也随之增长。单个DataNode从4T增长到36T,集群的尺寸增长到8000个DataNode。存储的需求从12PB增长到大于100PB。

(2)隔离问题

由于HDFS仅有一个NameNode,无法隔离各个程序,因此HDFS上的一个实验程序就很有可能影响整个HDFS上运行的程序。

(3)性能的瓶颈

由于是单个NameNode的HDFS架构,因此整个HDFS文件系统的吞吐量受限于单个NameNode的吞吐量。

2、HDFS Federation架构设计
考虑多个namenode同时工作,每一个namenode分别负责一个业务,这样,只需要增加namenode节点即可完成namenode不够用的情况。

你可能感兴趣的:(Hadoop生态,高可用)