Hadoop2 HA方案之QJM

喜欢一我的,能够为TA作任何事,获得不接受却依然心甘情愿鞍前马后,苦苦等候那一线但愿。对,这就是备胎,挂在汽车背后,可能一生也用不到的那个圆圈状的玩意儿,大部分状况下,它都会默默地挂在那里,等待几千分之一的机会,有个倒霉的轮子兄弟出事了,因而它就能派上用场了……(摘自豆瓣)html

在Hadoop的分布式文件系统HDFS中,NameNode用来保存文件系统的元数据(包含目录结构/数据块位置等),若是NameNode上的数据丢失,HDFS上对应的文件数据就没法找回来了。Hadoop在2.0.0以前的版本,使用SecondaryNameNode备份NameNode的数据,但SecondaryNameNode没法转成NameNode,若是NameNode挂了,整个HDFS就会挂掉,没法实现真正的failover。这篇博文总结了5种Hadoop HA(High Available,高可用)方案,Hadoop2以后官方引入了QJM(Quorum Journal Manager)和NFS用于NameNode的备份和切换。本方将介绍的是QJM方案,它使用第二个NameNode实时同步当前NameNode的数据,相比于SecondaryNameNode,他能够随时切换成为真正的NameNode(一个可转正的高级备胎)。node

先看看没有HA的HDFS的系统架构(用draw.io画的,尼马这么好的网站也被墙了):web

HDFS Architecture

而后有HA方案的系统架构:apache

HDFS HA Architecture

如下的实验基于4个节点的Hadoop集群。其中每一个节点的运行的进程列表以下:bootstrap

Role\Host hd1 hd2 hd3 hd4
NN
DN
JN
ZK

实验环境中,全部节点的运行环境基本相同:bash

  • Ubuntu14.04 X64
  • 4G内存
  • OpenJDK-1.7.0
  • 100Mbps以太网

下面是实现这个系统的流程(官方文档+我的注解+辅助Shell命令)。架构

1. 安装Hadoop系统。

严格按照单节点搭建集群搭建两个步骤,系统建起来彻底没压力。我遇到的问题是刚开始在配置文件(salves和core-site.xml等文件)中使用的是ip地址而非主机名,而后在log文件里看到各类没法链接。解决方案是修改主机名并在hosts文件里创建映射关系。app

hostname {new_hostname} # 修改主机名,只有当前Session有效
sudo vi /etc/hostname   # 永久修改主机名的方法

另外,对于64位的系统,最好从新编译源码。ssh

2. 修改配置文件。

hdfs-site.xml文件:分布式

<configuration>
  <property>
    <name>dfs.namenode.name.dir</name>
    <value>/data/hadoop/namenode</value>
  </property>
  <property>
    <name>dfs.datanode.data.dir</name>
    <value>/data/hadoop/datanode</value>
  </property>
  <property>
    <name>dfs.replication</name>
    <value>2</value>
  </property>
  <property>
    <name>dfs.nameservices</name>
    <value>mycluster</value>
  </property>
  <property>
    <name>dfs.ha.namenodes.mycluster</name>
    <value>nn1,nn2</value>
  </property>
  <property>
    <name>dfs.namenode.rpc-address.mycluster.nn1</name>
    <value>hd1:8020</value>
  </property>
  <property>
    <name>dfs.namenode.rpc-address.mycluster.nn2</name>
    <value>hd3:8020</value>
  </property>
  <property>
    <name>dfs.namenode.http-address.mycluster.nn1</name>
    <value>hd1:50070</value>
  </property>
  <property>
    <name>dfs.namenode.http-address.mycluster.nn2</name>
    <value>hd3:50070</value>
  </property>
  <property>
    <name>dfs.namenode.shared.edits.dir</name>
    <value>qjournal://hd1:8485;hd2:8485;hd4:8485/mycluster</value>
  </property>
  <property>
    <name>dfs.client.failover.proxy.provider.mycluster</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>/home/hduser/.ssh/id_rsa</value>
  </property>
  <property>
    <name>dfs.journalnode.edits.dir</name>
    <value>/data/hadoop/journalnode</value>
  </property>
</configuration>
  • 其中nameservices是集群的命名空间,即便有多个集群,能够共用配置文件,可是要注意某些配置项的顺序。
  • dfs.ha.namenodes.mycluster中的mycluster是能够任取的,可是要和dfs.nameservices对应。
  • dfs.namenode.rpc-address.mycluster.nn1参考上一条。
  • dfs.namenode.shared.edits.dir值的格式是"qjournal://host1:port1;host2:port2;host3:port3/journalId",用来指定对应的JN节点,journalId建议使用和nameservices相同的名称。
  • dfs.client.failover.proxy.provider.mycluster指定激活NameNode的Java类,目前Hadoop内置的只有上面那个。
  • dfs.ha.fencing.methods是来用来隔离失效的NameNode的方法,有sshfence和Shell两种方式。sshfence须要配置dfs.ha.fencing.ssh.private-key-files私钥文件,以便交互的过程不须要输入密码。
  • dfs.journalnode.edits.dir是JN保存数据的文件。

core-site.xml文件:

<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://mycluster</value>
    </property>
</configuration>
  • 注意mycluster要和dhfs-site.xml中的dfs.nameservices对应。fs.defaultFS不用端口号。

3. 部署

改好配置文件好,就要将配置文件同步到全部的机器上了。能够用rsync将文件同步到多台机器上。rsync是一个增量同步工具,须要先安装。下面的rsync.sh的功能是将当前目录的全部文件发送到文件或参数对应的机器上。

$ cat rsync.sh 
#! /bin/bash

dir=`pwd`
pdir=`dirname $dir`

send(){
    echo "Sending to $2:$1"
    rsync -avez -e ssh $1 $2:$3
}

mul_send(){
    while read host
    do
        send $dir $host $pdir
    done < $1
}

[ -f $1 ] && mul_send $1 || send $dir $1 $pdir

将rsync.sh放在etc/hadoop目录下,进入目录运行

chmod +x rsync.sh
./rsync.sh slaves
# or ./rsync.sh hostname

发送完文件以后,就是启动系统。步骤以下:

启动JNs.

在全部JournalNode上运行

sbin/hadoop-daemon.sh --script hdfs start journalnode

启动NameNode.

在原NameNode上运行

bin/hadoop --script hdfs start namenode # NameNode须要已经format。

(使用上面的rsync.sh文件)将原NameNode(nn1)上的数据复制到第二个NameNode(nn2)。而后在nn2上运行:

bin/hdfs namenode -bootstrapStandby

启动其余节点

在NameNode上运行

sbin/start-dfs.sh

4. 切换NameNode

手动方式

上面的NameNode默认以standby的状态启动,这时由于没有active的NameNode,因此是不能在HDFS读写文件,须要将其中的一个转成active状态。好比将nn1(对应前面的配置)转成Active:

bin/hdfs haadmin -transitionToActive nn1

而后在NameNode的web页面上部的括号里的standby变成active。
转成standby的命令是:

bin/hdfs haadmin -transitionToStandby nn1

自动切换

在当前NameNode不能使用时自动切换到第二个NameNode上,须要借助于ZooKeeper(ZK)。

ZK的安装过程和Hadoop差很少,就是下载文件、修改配置、复制到全部机器、启动。具体步骤在这里

配置文件conf/zoo.conf:

tickTime=2000
dataDir=/data/hadoop/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=hd2:2888:3888
server.2=hd3:2888:3888
server.3=hd4:2888:3888

hd2,hd3,hd4是主机名,至少须要三台,这个在一台机挂了整个系统还能用,ZK的数量通常是奇数。

而后要在hdfs-site.xml上添加配置:

<property>
    <name>dfs.ha.automatic-failover.enabled</name>
    <value>true</value>
</property>
<property>
    <name>ha.zookeeper.quorum</name>
    <value>hd2:2181,hd3:2181,hd4:2181</value>
</property>

而后就是在NameNode的机器上初始化NameNode在ZK的状态了:

bin/hdfs zkfc -formatZK

重启HDFS或手动启动DFSZKFailoverController(ZKFC):

sbin/stop-dfs.sh # 重启hdfs
sbin/start-dfs.sh
sbin/hadoop-daemon.sh start zkfc # 启动ZKFC

在该HA方案中,每个NameNode都有一个对应的ZKFC。ZKFC会随NameNode启动。

测试

在当前NameNode运行jps看NameNode的进程ID,而后kill掉。经过Web页面(http://hdx:50070),能够看到standby的NameNode几乎在kill的同时转成active了。

相关文章
相关标签/搜索