利用QJM实现HDFS的HA策略部署与验证工作记录分享

Linux大全评论3K views阅读模式

1、概述 

Hadoop2.X中的HDFS(Vsersion2.0)相比于Hadoop1.X增加了两个重要功能,HAFederationHA解决了Hadoop1.X  Namenode中一直存在的单点故障问题,HA策略通过热备的方式为主NameNode提供一个备用者,并且这个备用者的状态一直和主Namenode的元数据保持一致,一旦主NameNode挂了,备用NameNode可以立马转换变换为主NameNode,从而提供不间断的服务。另外,Federation特性,主要是允许一个 HDFS 集群中存在多个 NameNode 同时对外提供服务,这些 NameNode 分管一部分目录(水平切分),彼此之间相互隔离,但共享底层的 DataNode 存储资源。本文档主要是总结我自己个人利用为QJMQuorum Journal Manager)为公司测试集群(hadoop2.2.0)部署HA策略的过程以及自己在部署过程中遇到的一些问题。

2、HDFSHA基本架构

    先来看个手动挡切换的HA架构图:

利用QJM实现HDFS的HA策略部署与验证工作记录分享

 

    在一个典型的 HDFS  HA 场景中,通常由两个NameNode 组成,一个处于Active状态,另一个处于Standby状态。Active NameNode 对外提供服务,比如处理来自客户端的 RPC 请求,而 Standby NameNode 则不对外提供服务,仅同步 Active NameNode的状态,以便能够在它失败时快速进行切换。

为了能够实时同步 Active Standby 两个 NameNode 的元数据信息(实际上editlog,需提供一个共享存储系统,可以是 NFSQJQuorum Journal Manager)或者 BookeeperActive  NameNode 将数据写入共享存储系统,我们可以在Active  NameNode50070端口上看到相应的NameNode Journal  Status信息:利用QJM实现HDFS的HA策略部署与验证工作记录分享

同时Standby NameNode监听该系统(QJM管理下的Journalnode进程对应的存储路径),一旦发现有新数据写入,则读取这些数据,并加载到自己内存中,以保证自己内存状态与 Active NameNode 保持基本一致,那么在紧急情况下 standby NameNode便可快速切为Active NameNode。另外,在Hadoop1.X中的Secondary NameNode或者自己通过nfs热备的NameNode信息在Hadoop2.X中已经不再需要了,他们被Standby NameNode取代了。 在Yarn的官网中,我还看到一段关于JournalNode错误兼容性信息:利用QJM实现HDFS的HA策略部署与验证工作记录分享

大概意思是主备NameNode 之间通过一组JournalNode 同步元数据信息(我的通俗理解就是QJM类似一个数据池,池里边装着多个JournalNode进程存储editlogActive NameNode往池里边的JournalNode进程写editlogStandBy NameNode向池里边的JournalNode取数据同步),一条数据只要成功写入多数 JournalNode 即认为写入成功。启动的JournalNode的个数必须为奇数个。如果你的HA策略中启动了NJournalNode进程那么整个QJM最多允许(N-1)/2个进程死掉,这样才能保证editLog成功完整地被写入。比如 3 JournalNode 时,最多允许 1 JournalNode挂掉,5 JournalNode 时,最多允许 2 JournalNode 挂掉。

 

--------------------------------------分割线 --------------------------------------

 

Ubuntu 13.04上搭建Hadoop环境 http://www.linuxidc.com/Linux/2013-06/86106.htm

 

Ubuntu 12.10 +Hadoop 1.2.1版本集群配置 http://www.linuxidc.com/Linux/2013-09/90600.htm

 

Ubuntu上搭建Hadoop环境(单机模式+伪分布模式) http://www.linuxidc.com/Linux/2013-01/77681.htm

 

Ubuntu下Hadoop环境的配置 http://www.linuxidc.com/Linux/2012-11/74539.htm

 

单机版搭建Hadoop环境图文教程详解 http://www.linuxidc.com/Linux/2012-02/53927.htm

 

Hadoop中HDFS和MapReduce节点基本简介 http://www.linuxidc.com/Linux/2013-09/89653.htm

 

《Hadoop实战》中文版+英文文字版+源码【PDF】 http://www.linuxidc.com/Linux/2012-10/71901.htm

 

Hadoop: The Definitive Guide【PDF版】 http://www.linuxidc.com/Linux/2012-01/51182.htm

 

--------------------------------------分割线 --------------------------------------

 

3、  HDFS HA部署

 3.1、部署和测试环境

HDFS HA的部署和验证是在公司的测试集群中完成,其中测试集群中数据节点一共有4个主机名分别为hadoop-slave1hadoop-slave02hadoop-slave03hadoop-slave04master节点的主机名为hadoop-master。因为JournalNodeZookeeper进程是非常轻量级的,可以其他服务共用节点。现在的部署情况是:

hadoop-master:作为Active NameNode

haoop-slave01:  作为StandBy NameNode

hadoop-slave02: 作为DataNode,并且启动一个JournalNode、启动一个Zookeeper

hadoop-slave03: 作为DataNode,并且启动一个JournalNode、启动一个Zookeeper

hadoop-slave04: 作为DataNode,并且启动一个JournalNode、启动一个Zookeeper

其他软件:

Apache Hadoop 2.2.0JDK1.6

 

3.2、修改配置文件

 

主要配置${HADOOP_HOME}/etc/hadoop/下的hdfs-site.xml。下面是一些配置参数以及说明:

(1)      dfs.nameservices

HDFS的命名服务逻辑名称,可以自己定义。在已经配置HA策略的HDFS会用到这个逻辑名称,同时该名称也会被基于HDFS的系统用,例如HBASE等。另外,如果需要启动HDFS Federation的话,可以通过该参数指定多个服务逻辑名称,用“,”作为分隔符。

 我的配置如下:

 

<property>
   <name>dfs.nameservices</name>
    <value>mycluster</value>
    <description>Logical name forthis new nameservice</description>
</property>

 

(2)     dfs.ha.namenodes.[$nameserviceID]

命名服务下面包含的NameNode列表,可为每个NameNode 指定一个自定义的 ID 名称,比如命名服务 testCluster 下有两个 NameNode,分别命名为 nn1 nn2(到目前为止一个命名服务下最多包含2NameNode),我的配置如下:

 

<property>
    <name>dfs.ha.namenodes.testCluster</name>
    <value>nn1,nn2</value>
    <description>Unique identifiers for each NameNode in the nameservice </description>
</property>

 

(3)      dfs.namenode.rpc-address.[$nameserviceID].[$name node ID]

  这个参数很容易理解,主要是为每个NameNode设置RPC地址,我的配置如下:

<property>
   <name>dfs.namenode.rpc-address.testCluster.nn1</name>
    <value>hadoop-master:8020</value>
</property>
<property>
   <name>dfs.namenode.rpc-address.testCluster.nn2</name>
   <value>hadoop-slave01:8020</value>
</property>

(4)      dfs.namenode.http-address.[$nameserviceID].[$name node ID]

这个参数主要是为NameNode设置对外的HTTP地址, 通过此配置的指定你可以执行在浏览器中管理HDFS界面等操作。我的配置如下:

<property>
    <name>dfs.namenode.http-address.testCluster.nn1</name>
    <value>hadoop-master:50070</value>
</property>
<property>
    <name>dfs.namenode.http-address.testCluster.nn2</name>
    <value>hadoop-slave01:50070</value> 
</property>

(5)      dfs.namenode.shared.edits.dir

设置一组JournalNodeURL地址,ActiveNameNode会将Edit Log写入这些JournalNode所配置的本地目录(可以用nfs等共享文件系统,由参数dfs.journalnode.edits.dir控制)中,而StandByNameNode通过DataNode的心跳通知去读取这些Edit Log,并且作用在内存中的目录树中,其配置格式为:qjournal://host1:port1;host2:port2;host3:port3/journalId,我的配置如下:

<property>
       <name>dfs.namenode.shared.edits.dir</name>
       <value>qjournal://hadoop-slave02:8485;hadoop-slave03:8485;hadoop-slave04:8485/testcluster</value>
        <description>journalNodeList</description>
</property>

(6)      dfs.journalnode.edits.dir

这个就是刚刚提到的JournalNode所在节点上的一个目录,用于存放 editlog 和其他状态信息,该参数只能设置一个目录,你可以对磁盘做 RIAD 提高数据可靠性。

<property>
       <name>dfs.journalnode.edits.dir</name>
        <value>/home/hadoop/hadoop-2.2.0/journal/node/local/data</value>
</property>

(7)      dfs.client.failover.proxy.provider.[$nameserviceID]

该参数设置HDFS客户端与ActiveName进行交互的JAVA实现类,HDFS客户端通过该参数来寻找到集群中的Active NameNode,此类默认实现ConfiguredFailoverProxyProvider,我的配置如下:

<property>
        <name>dfs.client.failover.proxy.provider.testcluster</name>
       <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

(8)      dfs.ha.fencing.methods

这个参数比较重要,主要用于在主备节点切换时实现隔离机制的,在官方网站中做了相当详细的配置说明,其大概意思为:主备架构解决单点故障问题时,必须要认真解决的是脑裂问题,即出现两个 master 同时对外提供服务,导致系统处于不一致状态,可能导致数据丢失等潜在问题。在 HDFS HA中,JournalNode 只允许一个 NameNode 写数据,不会出现两个 Active NameNode 的问题,但是,当主备切换时,之前的 Active NameNode 可能仍在处理客户端的 RPC 请求,为此,需要增加隔离机制(fencing)将之前的 Active NameNode 杀死。HDFS 允许用户配置多个隔离机制,当发生主备切换时,将顺次执行这些隔离机制,直到一个返回成功。Hadoop 2.0 内部打包了两种类型的隔离机制,分别是 shell  sshfence

  1sshfence方式

sshfence 通过 ssh 登录到前一个 ActiveNameNode 并将其杀死。为了让该机制成功执行,需配置免密码 ssh 登陆(注意:这个为主备节点配置双向的RSA免密码登陆),这可通过参数 dfs.ha.fencing.ssh.private-key-files 指定一个私钥文件。我的配置如下:

<property>
        <name>dfs.ha.fencing.methods</name>
       <value>sshfence</value>
</property>
<property>
       <name>dfs.ha.fencing.ssh.private-key-files</name>
       <value>/home/hadoop/.ssh/id_rsa</value>
</property>

另外,在设置一个超时时间,一旦 ssh 超过该时间,则认为执行失败。我的配置如下:

<property>
   <name>dfs.ha.fencing.ssh.connect-timeout</name>
    <value>30000</value>
</property>

  2  shell方式(我没有采用这种方式)

        执行自定义的Shell脚本命令隔离旧的ActiveNameNode。相比于sshfence方式,个人认为这种方式有个好处就是,你在shell脚本里边可以将之前的 Active NameNode 直接kill掉,然后立马启动NameNode,此时刚刚启动的NameNode就是立马处于一个StandBy状态,立马就可以进入HA状态,如果采用sshfence方式还要手动自己重启刚刚被kill掉的NameNode从而才能进入HA(这些的前提都是,采用手动HA方式,之前的Acitve NameNode不是宕机而仅仅是NameNode进程挂掉)。配置可以为:

<property>
   <name>dfs.ha.fencing.methods</name>
   <value>shell(/path/to/my/script.sh arg1 arg2 ...)</value>
</property>

企鹅博客
  • 本文由 发表于 2019年7月17日 02:41:40
  • 转载请务必保留本文链接:https://www.qieseo.com/162755.html

发表评论