张子阳的博客

首页 读书 技术 店铺 关于
张子阳的博客 首页 读书 技术 店铺 关于

Hadoop 使用SecondaryNameNode进行故障恢复

2019-1-29 作者: 张子阳 分类: 大数据处理

SecondaryNameNode的作用不是做高可用,它是NameNode的一个辅助进程,用来合并fsimage和edits日志文件。但是,因为它保存了NameNode上元数据的副本(fsimage和edits),所以当NameNode出现故障时,可以使用它来做临时的NameNode,从而实现NameNode的故障恢复。这篇文章将记录如何实现这一过程。

NameNode和SecondaryNameNode的作用

简单来说,NameNode保存了集群的元信息:例如命名空间信息、块信息、存储位置等。这些信息以文件的形式保存在磁盘上,其位置由 $HADOOP_HOME/etc/hadoop/hdfs-site.xml中 的 dfs.namenode.name.dir 节点定义,默认位置是:file://${hadoop.tmp.dir}/dfs/name。

上面的${hadoop.tmp.dir}是hadoop的文件目录,它定义在core-site.xml文件的hadoop.tmp.dir节点。本文使用的是 /data/hadoop。

在我测试的机器上,它位于:/data/hadoop/dfs/name 下,该目录下有一个current文件夹和一个in_use.lock文件。其中current文件夹下保存了元数据,它的结构类似下面这样:

# ls /data/hadoop/dfs/name/current
edits_0000000000000014798-0000000000000014799  fsimage_0000000000000019703
edits_0000000000000014800-0000000000000014801  fsimage_0000000000000019703.md5
edits_0000000000000014802-0000000000000014803  fsimage_0000000000000019705
edits_0000000000000014804-0000000000000014805  fsimage_0000000000000019705.md5
edits_0000000000000014806-0000000000000014807  seen_txid
edits_0000000000000014808-0000000000000014809  VERSION

fsimage和edits文件的关系是这样的:

因此 fsimage + edits 就可以获得完整的元数据信息。

每当NameNode重启时,就将edits合并到fsimage,然后重新记录edits。但这样带来一个问题:NameNode在生产环境下很少重启,那么下次重启时需要合并的edits就变得非常多,从而需要花费比较长的时间。

简言之,在重启时 旧的fsimage+edits = 新的fsimage

于是SecondaryNameNode就出现了,它作为一个辅助进程来协助NameNode完成这项工作:

  1. 它间歇性地从NameNode获取未合并的edits文件,这个配置项是dfs.namenode.checkpoint.check.period,位于hdfs-site.xml,默认时间是60秒。
  2. 它间歇性地合并edits文件和fsimage,这个配置项是dfs.namenode.checkpoint.period,位于hdfs-site.xml,默认时间是3600秒,即1小时。
  3. 它将合并好的fsimage发回NameNode.

将SecondaryNameNode迁移至独立的服务器

本文的集群初始配置是这样的:

主机名 IP 作用
node0 192.168.1.56 NameNode, SecondaryNameNode, DataNode
node1 192.168.1.57 DataNode
node2 192.168.1.58 DataNode

目标就是将 SecondaryNameNode 从node0迁移至node1,然后停掉node0(模拟故障),并将node1作为NameNode重新启动(当然也可以是其他机器)。

在默认情况下,当使用 $HADOOP_HOME/sbin/start-dfs.sh 启动集群时,NameNode 和 SecondaryNameNode 位于执行start-dfs.sh的机器,DataNode位于 $HADOOP_HOME/etc/hadoop/slaves 文件中指定的机器。

dfs.namenode.secondary.http-address的默认值是:0.0.0.0:50090,代表本机。

修改$HADOOP_HOME/etc/hadoop/hdfs-site.xml,更改SecondaryNameNode的路径:

<property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>node1:50090</value>
</property>

<property>
    <name>dfs.namenode.secondary.https-address</name>
    <value>node1:50091</value>
</property>

在node0 (当前登录机器) 上重新执行 $HADOOP_HOME/sbin/start-dfs.sh:

# $HADOOP_HOME/sbin/start-dfs.sh
Starting namenodes on [node0]
node0: namenode running as process 1842. Stop it first.
node0: datanode running as process 30113. Stop it first.
node2: starting datanode, logging to /opt/hadoop/hadoop-2.9.1/logs/hadoop-root-datanode-dev58.out
node1: starting datanode, logging to /opt/hadoop/hadoop-2.9.1/logs/hadoop-root-datanode-dev57.out
Starting secondary namenodes [node1]
node1: starting secondarynamenode, logging to /opt/hadoop/hadoop-2.9.1/logs/hadoop-root-secondarynamenode-dev57.out

可以看到secondarynamenode将会在另一台机器上启动 (此处是node1)。

启动完后在node1和node2上分别执行下面的脚本,对比一下current下的文件,以及版本信息:

[node0] ls /data/hadoop/dfs/name/current
[node1] ls /data/hadoop/dfs/namesecondary/current

[node0] cat /data/hadoop/dfs/name/current/VERSION
[node1] cat /data/hadoop/dfs/namesecondary/current/VERSION

使用SecondaryNameNode来做故障恢复

注意,这里的故障恢复不是高可用。高可用由另外的更复杂的机制来实现,通常我们说高可用,是指无需人工介入的故障自动恢复。这里的故障恢复是需要人工参与的。

这里仅仅是利用SecondaryNameNode每60秒从NameNode同步一次元数据的特性,在NameNode出现故障时,将SecondaryNameNode作为NameNode进行启动,使得集群可以在短时间内恢复。

停止NameNode

为了做测试,我们可以手动停掉NameNode(node0),模拟其发生故障。在NameNode上执行下面的语句将其停掉:

# $HADOOP_HOME/sbin/hadoop-daemon.sh stop namenode

复制SecondaryNameNode下的元数据文件

此时NameNode(位于node0)已经不可访问,但我们可以在SecondaryNameNode(node1)上还原一份元数据。在node1上拷贝 ${hadoop.tmp.dir}/dfs/namesecondary 至 ${hadoop.tmp.dir}/dfs/name。

# cp -r /data/hadoop/dfs/namesecondary /data/hadoop/dfs/name

修改/etc/hosts,将原先NameNode的地址改为现在SecondaryNameNode的地址

要将NameNode切换到SecondaryNameNode上运行,我们还需要修改core-site.xml中fs.defaultFS项的配置,例如:

<property>
    <name>fs.defaultFS</name>
    <value>hdfs://node1:9000</value>
</property>

然后,使用下面的命令重新加载一下配置:

# hdfs dfsadmin -refreshNamenodes datanode:port
在本例中,有两台DataNode,分别是node1和node2,执行的是 hdfs dfsadmin -refreshNamenodes node1:50020

因为这种方法需要修改core-site.xml配置文件,将来机器恢复后还要再修改一遍,比较麻烦。还有一种更简单的方法,就是修改etc/hosts,将原本node1和node2上node0(原NameNode的地址),修改为node1的地址:

# cat /etc/hosts
192.168.1.57    node0
192.168.1.57    node1
192.168.1.58    node2
上面node0之前的地址是192.168.1.56,改为了192.168.1.57。
当集群中服务器很多时,要修改所有服务器的hosts,更好的办法是配置一个DNS服务器,专门用来解析IP。

重新启动NameNode

在新的node1上执行下面的语句,重新启动NameNode:

# $HADOOP_HOME/sbin/hadoop-daemon.sh start namenode

测试集群

可以通过执行下面的语句查看集群状态:

# hdfs dfsadmin -report

也可以通过NameNode的Web UI来查看。

http://namenode-ip:50070/dfshealth.html
对于本例而言,namenode-ip就是新切换到的node1的ip:192.168.1.57。

还可以通过执行文件的上传和下载来验证集群是否工作正常:

# hdfs dfs -put <local file> <hdfs file>
# hdfs dfs -get <hdfs file> <local file>
# hdfs dfs -rm -f <hdfs file>

总结

在这篇文章中,我们利用SecondaryNameNode自动同步NameNode元数据的特性,演示了当NameNode不可用时,将SecondaryNameNode作为NameNode进行启动的操作步骤。这里切换过后SecondaryNameNode和NameNode位于同一台机器。当然也可以使用独立的一台机器做为新的NameNode,此时将SecondaryNameNode上的元数据拷贝到新机器然后执行相应操作即可。

感谢阅读,希望这篇文章能给你带来帮助!