使用QJM实现HDFS的HA配置

使用QJM实现HDFS的HA配置

一、背景

hadoop 2.0.0以前,namenode存在单点故障问题(SPOF,single point of failure),若是主机或进程不可用时,整个集群就变得不可用,直到namenode进行重启或产生新的namenode。主要有两种方式会影响到HDFS集群:java

  • 不可预期事件好比机器宕机,集群变得不可用直到操做人员重启namenode。
  • 可预期事件好比软硬件升级也会致使集群的下线。

HDFS的高可用特性解决了以上两个问题,经过在一个集群中运行两个冗余的Namenode,分别以active/passiave配置方式实现一个热备处理。这容许namenode宕机后可以快速容灾到新节点,或者管理员以优雅的方式进行计划性运维容灾处理。node

二、架构

在电信的HA集群中,配置两台独立的主机为namenode。任什么时候刻,只有一台主机处于active状态,另外一台为standby状态。active节点负责集群中全部客户端的操做,standby节点只是扮演一个从属的角色,他会维护足够多的状态信息进行必要条件下的快速容灾处理。web

为了让standby节点同active节点保持状态同步,两个节点都须要同一组称之为“JournalNode”的进程通讯。当active节点对名字空间进行了修改后,都会记录这条修改记录到JN节点的半数以上节点。Standby节点便可从JN节点上读取这些编辑日志,Standby节点不断观察编辑日志的修改行为,若是有修改动做发生,便会马上应用到本身的名字空间中。容灾发生时,standby节点在切换到active状态前要确保从JN上读取了全部的修改动做。这能够保证在容灾发生前,名字空间的状态是彻底同步的。shell

为了提供快速容灾,让Standby节点拥有最新的block位置信息也是很是有必要的。为了作到这一点,须要使用两个namenode位置对Datanode进行配置,而且datanode会同时发送block信息和心跳信息给两个namenode。apache

正确操做HA集群的一个重点事项就是同一时刻只有一个namenode处于active状态,不然,名字空间状态很快在二者之间产生误差,从而致使数据丢失或不一致的风险。为了确保这一属性并防止所谓的“脑裂场景”,JournalNode节点只容许同一时刻一个namenode进行写入。容灾期间,成为active的namenode只是接管journalNode的写操做,有效防止其余的namenode节点,容许新的active节点安全处理容灾工做。bootstrap

三、硬件资源

为了部署HA集群,须要作以下准备:centos

  • namenode主机安全

    运行active和standby的namenode主机,他们具备相同的硬件配置,这种相同的硬件配置也会用在非HA集群下。session

  • Journalnode主机架构

    运行journalnode节点的主机。journalnode进程是轻量级进程,所以能够和他其余hadoop守护进程并存,例如namenode、resourcemanager等。注意:必须至少配置3个Journalnode守护进程,由于编辑日志必需要写入JN的半数以上。这容许系统容忍一台journalnode节点挂掉。为增长系统的容灾能力,应该运行奇数个journalnode节点,例如3,5,7台。当运行n个journalnode节点时,最多容忍(n - 1)/ 2节点故障。

注意,在HA集群模式下,standby节点也会对名字空间状态进行检查点操做,所以没有必要运行secondary namenode,checkpointnode或BackupNode。实际上,这样作会致使错误,这也运行经过改造非HA模式下的secondaryNode成为HA模式。

四、部署

4.1 配置概览

HA配置是向后兼容的,容许现有的namenode配置不作修改就能够工做。集群中全部节点具备相同的配置,而不须要个不一样主机依据节点类型进行不一样的配置。

HA集群使用nameservice id区分一个HDFS实例,他能够包含多个HA的namenode节点。集群中的Namenode使用惟一的namenode ID进行区分。为了对全部节点使用一个配置文件,配置可使用nameservice ID和namenode ID做为后缀。

4.2 配置细节

配置HA Namenode,须要添加几个选项给hdfs-site.xml配置文件。

这些选项的顺序并不重要,可是dfs.nameservicesdfs.ha.namenodes.[nameservice ID]值很关键,所以配置前须要肯定这些值的内容。

  • dfs.nameservices

    名称服务的逻辑名,该名称是任意的,将会用于配置和HDFS路径的受权。

    <property>
      <name>dfs.nameservices</name>
      <value>mycluster</value>
    </property>
  • dfs.ha.namenodes.[nameservice ID]

    名称服务中每一个namenode的惟一标识。使用“,”号分割的名称列表,datanode经过他来检测集群中的全部namenode。

    <property>
      <name>dfs.ha.namenodes.mycluster</name>
      <value>nn1,nn2</value>
    </property>

    注意:目前最多只支持两个名称节点。

  • dfs.namenode.rpc-address.[nameservice ID].[name node ID]

    配置每一个名称节点的IPC端口,须要在单独的元素进行配置。

    <property>
      <name>dfs.namenode.rpc-address.mycluster.nn1</name>
      <value>s101:8020</value>
    </property>
    <property>
      <name>dfs.namenode.rpc-address.mycluster.nn2</name>
      <value>s102:8020</value>
    </property>

  • dfs.namenode.http-address.[nameservice ID].[name node ID]

    配置每一个namenode的http监听地址。

    <property>
      <name>dfs.namenode.http-address.mycluster.nn1</name>
      <value>s101:50070</value>
    </property>
    <property>
      <name>dfs.namenode.http-address.mycluster.nn2</name>
      <value>s102:50070</value>
    </property>

  • dfs.namenode.shared.edits.dir

    namenode从JNs集合上读写日志的uri地址。

    <property>
      <name>dfs.namenode.shared.edits.dir</name>
      <value>qjournal://s102:8485;s103:8485;s104:8485/mycluster</value>
    </property>

  • dfs.client.failover.proxy.provider.[nameservice ID]

    容灾代理提供商类,用来检测哪一个namenode是active状态,哪一个namenode用来服务于客户端请求。当前hadoop只有一个实现。

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

  • dfs.ha.fencing.methods

    容灾期间防御namenode的java类或者脚本列表。使用QJM(Quorum journal manager)时只容许一个namenode向journalnodes写入数据,所以不存在由于脑裂损坏系统元数据的可能。可是,容灾发生时,依然有可能的是上一个active节点向客户端提供读请求服务,直到向JN节点写入数据失败形成namenode中止后致使的时间过时。基于这一缘由,使用QJM时仍有必要配置一些防御方法。为提高系统在防御事件失败时的可用性,建议配置防御方法确保列表中最后一个防御方法返回成功。注意若是选择使用并没有实际的防御方法,也要进行一些配置,好比“shell(bin/true)”等。

    防御方法能够配置成列表,而后按序调用直到防御方法成功为止。hadoop给出了两种方式:shell和sshfence。自定义防御方法能够实现org.apache.hadoop.ha.NodeFencer类。

    防御方法配置成多行列表的形式,容灾时按顺序进行调用直到防御方法返回成功为止。hadoop有两种方式:shell和sshfence。自定义的话能够实现org.apache.hadoop.ha.NodeFencer类。

    sshfence方式是ssh到active的namenode节点并将进程杀死,该中方式必须可以无密登陆到目标节点,所以必需要配置私钥(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/centos/.ssh/id_rsa</value>
    </property>

    shell方式是运行一个shell脚原本防御active namenode。配置方式以下:

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

  • fs.defaultFS

    hadoop文件系统客户端没有指定前缀时使用的默认路径前缀。

    <property>
      <name>fs.defaultFS</name>
      <value>hdfs://mycluster</value>
    </property>

  • dfs.journalnode.edits.dir

    Journanode守护进程存放本地状态的路径,该路径使用绝对路径,使用一个路径便可。

    <property>
      <name>dfs.journalnode.edits.dir</name>
      <value>/path/to/journal/node/local/data</value>
    </property>

4.3 部署细节

配置完成后,必须在JN节点启动全部的JN守护进程,可以使用以下命令完成:

hadoop-daemon.sh start journalnode

一旦JN进程启动完成,必需要对两个HA的namenode节点的磁盘元数据进行初始同步

  • 若是搭建的是全新的hdfs集群,应该在其中的一个namenode上运行以下命令进行格式化

    hdfs namenode -format
  • 若是已经格式化过namenode或者转换非HA模式到HA模式下,须要复制namenode的元数据目录到另外一个namenode相同目录下,未格式化的namenode节点运行以下命令,完成待命状态引导。该命令还会保证jn节点包含足够多了编辑动做,以便可以启动两个namenode节点。

    hdfs namenode -bootstrapStandby
  • 若是正在将非HA模式转换成HA,你应该运行以下命令,将会从本地namenode的编辑日志初始化到JN节点的编辑数据。

    hdfs namenode -initializeSharedEdits

此时能够像以往启动namenode同样启动两个namenode。同时,能够分别使用两个namenode各自的webui地址查看各自的状态。你会发现两台namenode的状态都是standby。

http://s101:50070
http://s105:50070

4.4 管理命令

配置并启动namenode后,就能够进行管理工做,可使用以下管理命令对namenode进行管理:

Usage: haadmin
    [-transitionToActive <serviceId>]
    [-transitionToStandby <serviceId>]
    [-failover [--forcefence] [--forceactive] <serviceId> <serviceId>]
    [-getServiceState <serviceId>]
    [-checkHealth <serviceId>]
    [-help <command>]
  • transitionToActive和transitionToStandby

    切换状态到active或standby状态,这些命令不会进行防御处理,尽可能少使用,而是用使用failover代替。

  • failover

    在两个namenode间进行容灾演练,从第一个nn到第二个nn进行容灾处理,若是第一个nn是standby,就将第二个nn变换成active态。若是第一个是active,首先尝试优雅变换到standby状态。若是这一个过程失败,就按序执行防御方法直到成功,此过程事后,第二个nn才会变成active态。若是防御方法都没有成功,则第二个nn就不会变成active态并返回一个错误。

  • getServiceState

    检测指定的nn的状态,链接到namenode检测其状态,打印active或standby字样。

  • checkHealty

    检查给定namenode的健康情况,namenode本省可以执行一个诊断工做,包括检查是否内部服务在进行,若是健康返回0,不然返回非0。

    注意该命令还未实现,始终返回0,除非namenode彻底中止。

五、自动容灾

5.1 介绍

以上部分描述了如何配置手动容灾,在该模式下,系统没法自动触发容灾处理,哪怕是active挂掉。本章描述如何配置自动容灾。

5.2 组件

自动容灾引入两个新组件:一个是Zookeeper的quorum,一个是ZKFailoverController进程(简称zkfc)。

apache zookeeper是高可用服务用于维护少许协同数据,通知客户端数据变动、监控客户端故障。自动容灾依赖zookeeper一下内容:

  • 故障检测

    集群中每一个namenode主机都在zookeeper中维护了永久session。若是机器宕机,session就会超时,通知其余namenode触发容灾。

  • active namenode选举

    zookeeper提供一种简单机制可以以独占方式选举一个node为active。若是当前active节点宕机,另外一个namenode就会接管一个排他锁代表本身将成为下一个active。

zkfc是zookeeper客户端管理监控namenode状态的新组件。每一个运行namenode主机都会运行一个zkfc进程。zkfc进程负责以下工做:

  • 监控检查

    zkfc周期性ping本地namenode的状态,若是namenode可以及时响应,则认为namenode是健康的。若是node宕机或进入某种不监控状态,监控器就标记其位不健康状态。

  • zk session管理

    若是本地namenode是健康的,zkfc会持有zk的session。若是namenode是健康的,zkfc还会持有一把临时锁。若session过时,lock节点将会被删除。

  • 基于zk的选举

    若是namenode是健康的,zkfc就会知道不会有其余人持有lock节点,本身就会尝试上锁。如若成功就赢得选举,并运行容灾程序,本地namenode就成为active状态。

5.3 部署zookeeper

典型配置zookeeper模式是使用3或5个节点,因为zookeeper是轻量级的,所以能够和其余进程位于同一主机,例如namenode或datanode。许多人选择部署第三节点在ResourceManager主机上。建议配置zookeeper在单独的磁盘驱动器上存储数据,同hdfs元数据分开,以得到更好的性能和隔离处理。搭建zookeeper集群请参考相关文章,这里不作介绍。

5.4 开始前准备工做

中止hdfs集群。

5.5 配置自动容灾

在hdfs-site.xml文件中添加以下配置启用自动容灾。s

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

在core-site.xml文件中添加zk节点地址。

<property>
    <name>ha.zookeeper.quorum</name>
    <value>s102:2181,s103:2181,s104:2181</value>
 </property>

5.6 在zk中初始化HA状态

在其中的一个namenode节点上运行以下命令:

hdfs zkfc -formatZK

该命令会在zk中建立相应节点存储用于容灾的数据。

5.7 使用start-dfs.sh启动集群

因为已经启用了自动容灾,所以启动namenode时,会自动启动zkfc进程,并自动选举一个namenode为active节点。

5.8 手动启动zkfc进程

也能够手动启动zkfc进程,运行以下命令:

$>hadoop-daemon.sh start zkfc
相关文章
相关标签/搜索