从零开始搭建HDFS高可用(HA)环境(使用QJM)

背景

      在Hadoop 1.x 中,Namenode是集群的单点故障,一旦Namenode出现故障,整个集群将不可用,重启或者开启一个新的Namenode才能够从中恢复。值得一提的是,Secondary Namenode并没有提供故障转移的能力。集群的可用性受到影响表现在:

  • 当机器发生故障,如断电时,管理员必须重启Namenode才能恢复可用。
  • 在日常的维护升级中,需要停止Namenode,也会导致集群一段时间不可用。

架构演变

一、普通的HDFS架构

这里写图片描述
这是最简单的HDFS架构,一个集群只有一个NameNode,一旦由于某种原因它发生故障这整个HDFS将无法工作。

二、两个NN的HDFS架构

      在典型的HA集群中我们配置两个完全独立的机器为NameNode,但是,在同一时间一个设置为Active状态(活跃),一个设置为Standby状态(备用)。活跃状态的机器保持和客户端的读写服务,而备机只是用于发生故障时的快速切换。
      当活跃状态的机器发生故障崩溃时备机是没有对应的元数据信息的,故障后又不可能再从主机获取了,所以为了使备机的切换快速应该使主机和备机保持一个同步状态。两个NameNode为了数据同步,会通过一组称作JournalNode(3个以上且为奇数个)的独立进程进行相互通信。当active状态的NameNode的命名空间有任何修改时,会告知大部分的JournalNodes进程。standby状态的NameNode有能力读取JNs中的变更信息,并且一直监控edit log的变化,把变化应用于自己的命名空间。standby可以确保在集群出错时,命名空间状态已经完全同步了。
      为了确保快速切换,Standby状态的NameNode有必要知道集群中所有数据块的位置。为了做到这点,所有的datanode必须配置两个NameNode的地址,发送数据块位置信息和心跳给他们两个。
      对于HA集群而言,确保同一时刻只有一个NameNode处于active状态是至关重要的。否则,两个NameNode的数据状态就会产生分歧,可能丢失数据,或者产生错误的结果。为了保证这点,JN必须确保同一时刻只有一个NameNode可以向自己写数据。架构如下图所示:
这里写图片描述
      到这里为止初步实现了个HA的HDFS集群,但是一旦故障发生备用的NameNode是不会主动转为活跃状态的,人工切换。

三、自动切换的两个NN的HDFS架构

      为实现NN的自动切换需要引入Zookeeper。使用Zookeeper Quorum和ZKFailoverController process(简称ZKFC)这两个组件。所以在部署HDFS的前我们需要使用至少三台(奇数)机器搭建一个小小的ZK集群。
Zookeeper的任务包括:

  • 失败检测:
    每个Namnode都在ZK中维护一个持久性session,如果Namnode故障,session过期,使用zk的事件机制通知其他Namenode需要故障转移。
  • Namenode选举:
    如果当前Active namenode挂了,另一个namenode会尝试获取ZK中的一个排它锁,获取这个锁就表名它将成为下一个Active NN。

在每个Namenode守护进程的机器上,同时也会运行一个ZKFC,用于完成以下任务:

  • Namenode健康检查
  • ZK Session管理
  • 基于ZK的Namenode选举

      如果ZKFC所在机器的Namenode健康状态良好,并且用于选举的znode锁未被其他节点持有,则ZKFC会尝试获取锁,成功获取这个排它锁就代表获得选举,获得选举之后负责故障转移,如果有必要,会fencing掉之前的namenode使其不可用,然后将自己的namenode切换为Active状态。结构图如下:
这里写图片描述

环境搭建

      我准备了10台linux(64位Centos6.5)服务器(node1~node10)使用ntpdate cn.pool.ntp.orghwclock --systohc将10台机器时间设置一致,安装jdk1.7,hadoop版本为2.5.1,Zookpeer版本为3.4.6。
资源下载:
Hadoop2.5.1
Zookpeer3.4.6

Zookpeer集群搭建

切记先将防火墙关闭,我在第一次安装时没有关闭防火墙导致安装失败。

在搭建HDFS前我们要先搭建ZK集群。选择3台机器(node8~node10)搭建。
1、将zookeeper3.4.6上传至/home目录下,解压:tar -zxvf zookeeper-3.4.6.tar.gz
2、在zookeeper-3.4.6的conf目录下创建一个名为zoo.cfg的文件,文件内容为:

tickTime=2000
dataDir=/opt/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=node8:2888:3888
server.2=node9:2888:3888
server.3=node10:2888:3888

dataDir可以自己设置,nodeX根据自身服务器进行设置。server.X列出构成ZooKeeper服务的服务器。当服务器启动时,它通过在数据目录(即上面的dataDir)中查找文件myid来知道它是哪个服务器。所以我们需要在三个机器dataDir对应的目录下创建一个myid文件,里面的值就是X的值。

现在我们在三个机器上就可以启动ZK了:

扫描二维码关注公众号,回复: 2505385 查看本文章
cd /home/zookeeper-3.4.6/bin
./zkServer.sh start

这里写图片描述
你可以查看/home/zookeeper-3.4.6/bin下的日志文件zookeeper.out来判断是否出错。

使用zkServer.sh status查看zk状态:
node8:
这里写图片描述
node9:

node10:
这里写图片描述

ZK集群启动完毕后就不需要关闭了,现在我们来安装高可用HDFS。

高可用HDFS搭建

一、配置文件的编写

1、配置hadoop目录下的hdfs-site.xml文件,添加如下配置:

<property>
    <name>dfs.nameservices</name>
    <value>hcpcluster</value> #这个名字自定义,记住这个值,在后续配置中一直使用
</property>
<property>
    <name>dfs.ha.namenodes.hcpcluster</name>
    <value>nn1,nn2</value> #选择两个节点作为NN,名字设置为nn1和nn2
</property>
<property>
    <name>dfs.namenode.rpc-address.hcpcluster.nn1</name>
    <value>node1:8020</value> #选择node1为NN
</property>
<property>
    <name>dfs.namenode.rpc-address.hcpcluster.nn2</name>
    <value>node2:8020</value> #选择node2为NN
</property>
<property>
    <name>dfs.namenode.rpc-address.hcpcluster.nn1</name>
    <name>dfs.namenode.http-address.hcpcluster.nn2</name>
    <value>node2:50070</value>
</property>
<property>
    <name>dfs.namenode.shared.edits.dir</name>    <value>qjournal://node5:8485;node6:8485;node7:8485/hcpcluster</value>  
</property>
<property>
    <name>dfs.client.failover.proxy.provider.hcpcluster</name>
    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
    <name>dfs.ha.fencing.methods</name>
    <value>sshfence</value>
</property>
<property>
    <name>dfs.ha.fencing.ssh.private-key-files</name>
    <value>/root/.ssh/id_rsa</value>
</property>
<property>
    <name>dfs.journalnode.edits.dir</name>
    <value>/opt/journalnode</value>
</property>

2、配置core-site.xml文件,添加如下配置:

<property>
    <name>fs.defaultFS</name>
    <value>hdfs://hcpcluster</value>
</property>   
<property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/hadoop-2.5</value>
</property>

3、配置到这里还是没有完成,到此整个HDFS集群仍然做不到自动切换,若要则需要在hdfs-site.xml中添加如下配置:

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

在core-site.xml中添加如下配置:

<property>
    <name>ha.zookeeper.quorum</name>
    <value>node8:2181,node9:2181,node10:2181</value>
</property>

4、配置DataNode,我选择node2,node3,node4为DataNode,在slaves中配置:

node2
node3
node4

二、启动journalnode

我选择了node5,node6,node7作为journalnode,现在需要将他们都启动。

hdfs-daemon.sh start journalnode

这里写图片描述
查看对应的日志文件判断是否启动成功。

三、启动HDFS

1、在其中一台NameNode上进行格式化操作,使用以下命令:

hdfs namenode -format

2、在另外一台NameNode中执行以下命令以格式化产生的元数据:

hdfs namenode -bootstrapStandby

其实我们也可以手动复制格式化产生的元数据到指定目录(目录在core-site.xml中配置了的)

3、初始化Zookeeper所需的状态。在一个NameNode中执行以下命令:

hdfs zkfc -formatZK

这将创建一个znode用于ZK的自动故障转移系统存储数据。

4、启动HDFS:

start-dfs.sh

这里写图片描述

通过浏览器访问两个NameNode:
这里写图片描述
这里写图片描述
可以发现两个NN其中一个在active状态,另外一个在standby状态。

四、检测自动切换

      虽然我们可以发现两个处于不同状态的NN,但是这并不意味着当其中一个NN故障后另外一个会自动激活。
      现在我将node1中的namenode杀死,查看node2是否会切换:
这里写图片描述
这里写图片描述
很遗憾!没有自动切换。
因为node2没有自动切换所有我们需要查看node2中zkfc的日志:
这里写图片描述
原来是我在core-site.xml中没有配置

<property>
   <name>ha.zookeeper.quorum</name>
   <value>node8:2181,node9:2181,node10:2181</value>
</property>

再次启动hdfs后Zookeeper将node2投为active了,不打紧。
这里写图片描述
这里写图片描述
现在我杀死node2中的namenode:
这里写图片描述
查看node1的状态,成功转为active:
这里写图片描述
搭建成功!!!

猜你喜欢

转载自blog.csdn.net/qq_25343557/article/details/81165021
今日推荐