内容简介:SecondaryNameNode的作用不是做高可用,它是NameNode的一个辅助进程,用来合并fsimage和edits日志文件。但是,因为它保存了NameNode上元数据的副本(fsimage和edits),所以当NameNode出现故障时,可以使用它来做临时的NameNode,从而实现NameNode的故障恢复。这篇文章将记录如何实现这一过程。简单来说,NameNode保存了集群的元信息:例如命名空间信息、块信息、存储位置等。这些信息以文件的形式保存在磁盘上,其位置由 $HADOOP_HOME/et
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 - 保存了自某一历史时刻之后的变更信息
因此 fsimage + edits 就可以获得完整的元数据信息。
每当NameNode重启时,就将edits合并到fsimage,然后重新记录edits。但这样带来一个问题:NameNode在生产环境下很少重启,那么下次重启时需要合并的edits就变得非常多,从而需要花费比较长的时间。
简言之,在重启时 旧的fsimage+edits = 新的fsimage
于是SecondaryNameNode就出现了,它作为一个辅助进程来协助NameNode完成这项工作:
- 它间歇性地从NameNode获取未合并的edits文件,这个配置项是dfs.namenode.checkpoint.check.period,位于hdfs-site.xml,默认时间是60秒。
- 它间歇性地合并edits文件和fsimage,这个配置项是dfs.namenode.checkpoint.period,位于hdfs-site.xml,默认时间是3600秒,即1小时。
- 它将合并好的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上的元数据拷贝到新机器然后执行相应操作即可。
感谢阅读,希望这篇文章能给你带来帮助!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 记一次 Kafka 集群的故障恢复
- 数据库故障恢复机制的前世今生
- ORA-600 kokasgi1故障恢复
- Elasticsearch 最佳实践系列之分片恢复并发故障
- Windows故障转移群集(WSFC)的备份和恢复
- 数据库ORA-01196故障-归档日志丢失恢复详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。