Spark平台(高级版五)Hadoop_HDFS

完整目录、平台简介、安装环境及版本:参考《Spark平台(高级版)概览》

5.2 HDFS

5.2.1 HDFS基本原理

5.2.1.1 目标
  • 能够高度容错,硬件的差异性,在硬件出现故障时,保证系统的一致性;
  • 保证streaming data的处理,各式各样的文件系统,包括NTFS、FAT、EXT等,HDFS区别在于是面向数据处理应用的文件系统,高吞吐量,低延迟;
  • 大数据集,HDFS上的文件,可能是TB、PB甚至更大;
  • 简单的一致性模型,HDFS里面的文件一次写入,多次存取,不支持在文件中间的某个点增加内容,但是支持在文件结尾增加;
  • HDFS是数据存储框架,将计算搬移到数据所在的节点上,而不是将计算独立于数据之外,这样更能够提高系统性能,这就是多为的本地化计算;
  • 能够适用于多种软硬件平台。
5.2.1.2 架构

如图展示了HDFS整体架构,该架构包括三个角色:

Client:读取文件时,先从NameNode获取文件的元数据信息,然后再去通过DataNode读取文件的块内容;

NameNode:文件的元数据管理主键,整个系统的大脑,知道每一个文件的每一个块存在哪一个DataNode中;

DataNode:存储数据块。

HDFS通过数据库的冗余复制能够达到容错的性能,即同一个数据块有多个数据块的冗余备份。

Rack:类似机架概念,每一个机架里面有一个告诉传输通道,如光纤或GB级别的以太网,相当于内网/局域网高性能的传输。

5.2.1.3 数据块

文件系统块一般为几千字节,而磁盘块一般为512字节。

HDFS也有块的概念,默认为128MB,HDFS上的文件被划为为大小的多个分块作为独立的存储单元,不同于单一磁盘文件系统的是,HDFS中小于一个块大小的文件不会占用整个块空间。

HDFS块比磁盘块大是为了减少寻址开销,随着磁盘传输速率的提升,块会设置的越来越大。但是由于MapReduce中的Map操作通常一次只处理一个块的数据,如果设置过大,导致任务数太少,运行速度就会变慢。

块适合用于数据备份而提高容错能力和可用性,默认将每个块复制到3台相互独立的机器上,确保块在发生故障时数据不会丢失。

5.2.1.4 namenode和datanode

机器包括一个namenode和多个datanode。

namenode维护文件系统树即整棵树内所有的文件和目录,这些信息以文件信息保存在本地磁盘。如果该系统文件损坏,文件系统上的所有文件都会丢失,因为单独根据datanode是无法重建整个文件系统的。

datanode记录每个文件中各个块所在的数据节点信息,但是并不会永久保存块的位置信息,源于信息会在系统启动时重建。作为文件系统的工作节点,可以根据需要存储并检索数据块,定期向namenode发送其所存储的块列表。

由于namenode容错非常重要,需要对该节点做备份,如HA。

5.2.1.5 高可用性

由于namenode是唯一存储元数据与文件到数据块映射的地方,一旦发生胆小失效,所有作业都将无法进行。

要想恢复一个失效的namenode,需要有一个文件系统元数据副本,还需要一序列的重建操作,恢复时间长。

为此hadoop提供了HA支持,配置一对主备namenode,当活动的namenode失效是,备用的namenode接管任务并开始接受来自客户端的请求,不会出现中断现象。为了实现HA,hadoop做了一些修改:namenode间共享日志,便于备用主备状态同步;datanode需要向主备namenode发送数据块信息。

使用故障转移控制器确保仅有一个活动的namenode,主备namenode都运行着一个轻量的故障转移控制器,监控主namenode是否失效并及时进行故障切换。

5.2.2 基本操作

用ssh登录app-11节点,切换到hadoop用户,并启动集群。

通过hdfs查看命令内容:hdfs

  • 第一类是管理命令;
  • 第二类是client端的一些命令;
  • 第三类是管理守护进程的命令。
5.2.2.1 版本信息
命令:hdfs version
5.2.2.2 路径信息classpath
命令:hdfs classpath
5.2.2.3 配置信息getconf
hdfs getconf -namenodes

hdfs getconf –secondaryNameNodes

hadoop2.0的HA机制之后,SecondaryNameNode,CheckpointNode,BackupNode这些都不需要了。

hdfs getconf -journalNodes
hdfs getconf –includeFile

DameNode节点可以动态加入和删除,需要配置NameNode的hdfs-site.xml,增加dfs.hosts.exclude配置,同时在对应路径下新建excludes文件,并写入待删除DataNode的ip或域名,接这在NameNode上刷新所有DataNode,就可以可以观测到DataNode逐渐变为Dead。

5.2.2.4 文件操作dfs

类似LINUX文件的操作:hdfs dfs

如,根目录创建一个文件/test2

hdfs dfs -mkdir /test2

将之前案例运行结果文件/test/output/part-r-00000拷贝到/test2中:

hdfs dfs -cp /test/output/part-r-00000 /test2

将文件/test2/part-r-00000下载到当前位置

hdfs dfs -get /test2/part-r-00000 ./

试验完后删除该文件:

rm -rf part-r-00000

5.2.3 HDFS HA配置文件详解

本部分详细分析hadoop配置文件,特别是HDFS做HA的配置。

Hadoop2.0版本之前,NameNode是存在单点故障的,因为只有一个NameNode,一旦挂掉,集群将存在不可用的状态,由于NameNode存的是整个文件系统的元数据信息,因此在2.0开始,hadoop HDFS采用了高可用性方案,同时有多个NameNode运行,一个活动的NameNode,其他的作为备用的NameNode。

活动的NameNode,负责执行所有修改名字空间(文件目录)、删除备份数据块等操作。备份的NameNode执行同步操作,包括所有对名字空间、数据块删除操作的信息备份,这样能够保证所有NameNode节点看见的文件视图是一致的,当活动的NameNode发生故障后,备份NameNode切换回来,能够保证正确的文件系统结构。

为了保证主备NameNode通讯顺畅,hadoop运行了一组独立的JournalNodes节点,每个NameNode都可以和所有的JournalNode通讯,将所有的修改信息存在JournalNode上,HDFS将执行操作记录存储在EDITLOG中,并且将日志写入JournalNode中。备份NameNode一直监听JournalNodes的EDITLOG变化,当监测到发生变化后,将变化的信息和自己本地存储的信息进行合并,这样就可以看到最新的文件系统的状态和结构信息。

接下来通过配置文件对比进行分析,主要分析和HDFS做HA相关的文件。

5.2.3.1 core-site.xml
/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/core-site.xml
<configuration>
	<!-- hdfs地址,ha模式中是连接到nameservice  -->
	<property>
		<name>fs.defaultFS</name>
		<value>hdfs://dmcluster</value>
	</property>
	<!-- 指定ZooKeeper集群的地址和端口。注意,数量一定是奇数,且不少于三个节点-->
	<property>
		<name>ha.zookeeper.quorum</name>
		<value>app-11:2181,app-12:2181,app-13:2181</value>
	</property>
	<!-- 这里的路径默认是NameNode、DataNode、JournalNode等存放数据的公共目录,也可以单独指定 -->
	<property>
		<name>hadoop.tmp.dir</name>
		<value>/hadoop/Hadoop/hadoop-3.1.2/tmp</value>
	</property>
	<!-- 配置该superUser允许通过代理访问的主机节点-->
    <property><name>hadoop.proxyuser.hadoop.hosts</name><value>*</value></property>
	<!-- 配置该superUser允许代理的用户所属组-->
    <property><name>hadoop.proxyuser.hadoop.groups</name><value>*</value></property>
	<!-- 增加以上配置后,无需重启集群,可以直接用hadoop管理员账号重新加载这两个属性值-->
</configuration>

fs.defaultFS:有可能会存在多个集群,defaultFS操作默认集群所对应的HDFS。

ha.zookeeper.quorum:关于zookeeper的,hadoop做HA,相当于client端,需要配置client的端口号以及整个zookeeper的集群的所有的服务器。

hadoop.tmp.dir:将所有信息限制在hadoop-3.1.2安装包的根目录下。

5.2.3.2 hdfs-site.xml
/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/hdfs-site.xml
<configuration>
	<!-- 指定副本数,不能超过机器节点数  -->
	<property>
		<name>dfs.replication</name>
		<value>3</value>
	</property>
	<!-- 为namenode集群定义一个services name -->
	<property>
		<name>dfs.nameservices</name>
		<value>dmcluster</value>
	</property>
	<!-- 配置namenode和datanode的工作目录-数据存储目录 -->
	<property>
		<name>dfs.namenode.name.dir</name>
		<value>/hadoop/Hadoop/hadoop-3.1.2/hdfs/name</value>
	</property>
	<!-- 配置namenode和datanode的工作目录-数据存储目录 -->
	<property>
		<name>dfs.datanode.data.dir</name>
		<value>/hadoop/Hadoop/hadoop-3.1.2/hdfs/data</value>
	</property>
	<!-- nameservice 包含哪些namenode,为各个namenode起名 -->
	<property>
		<name>dfs.ha.namenodes.dmcluster</name>
		<value>nn1,nn2</value>
	</property>
	<!-- namenode间用于共享编辑日志的journal节点列表 -->
	<property>
		<name>dfs.namenode.shared.edits.dir</name>
		<value>qjournal://app-11:8485;app-12:8485;app-13:8485/dmcluster</value>
	</property>
	<!-- 客户端连接可用状态的NameNode所用的代理类 -->
	<property>
		<name>dfs.client.failover.proxy.provider.dmcluster</name>
		<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
	</property>
	<!-- 一旦需要NameNode切换,使用ssh方式进行操作 -->
    <property>
		<name>dfs.ha.fencing.methods</name>
		<value>shell(/bin/true)</value>
    </property>
	<!-- 指定该集群出现故障时,是否自动切换到另一台namenode -->
	<property>
		<name>dfs.ha.automatic-failover.enabled</name>
		<value>true</value>
	</property>
	<!-- journalnode 上用于存放edits日志的目录 -->
	<property>
		<name>dfs.journalnode.edits.dir</name>
		<value>/hadoop/Hadoop/hadoop-3.1.2/data/journals</value>
	</property>
	<!-- 名为master188的namenode的rpc地址和端口号,rpc用来和datanode通讯 -->
	<property>
		<name>dfs.namenode.rpc-address.dmcluster.nn1</name>
		<value>app-12:8020</value>
	</property>
	<!--名为master188的namenode的http地址和端口号,用来和web客户端通讯 -->
	<property>
		<name>dfs.namenode.http-address.dmcluster.nn1</name>
		<value>app-12:9870</value>
	</property>
	<!-- 名为master189的namenode的rpc地址和端口号,rpc用来和datanode通讯 -->
	<property>
		<name>dfs.namenode.rpc-address.dmcluster.nn2</name>
		<value>app-11:8020</value>
	</property>
	<!-- 名为master189的namenode的http地址和端口号,用来和web客户端通讯 -->
	<property>
		<name>dfs.namenode.http-address.dmcluster.nn2</name>
		<value>app-11:9870</value>
	</property>
</configuration>

dfs.nameservices:由于可以做Federation,那么需要定义每个集群所处的命名空间,可以定义多个,相当于有多个HDFS集群。定义为dmcluster,访问的时候就可以通过hdfs://dmcluster:hadoop进行此集群的hadoop目录。

dfs.namenode.name.dir:存储操作相关的信息;

dfs.datanode.data.dir:存储操作相关的信息;

dfs.ha.namenodes.dmcluster:值表示有两个NameNode节点,nn1和nn2;

dfs.namenode.shared.edits.dir:定义JournalNode节点

后续定义了每一个NameNode的rpc-address和http-address。

5.2.3.3 workers
/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/workers
app-11
app-12
app-13

写入三台机器的名称或者IP地址,默认是localhost,即不加配置的启动整个hadoop,可以得到一个单节点运行的hadoop环境。

5.2.3.4 hadoop-env.sh
/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/hadoop-env.sh
export JAVA_HOME=/hadoop/JDK/jdk1.8.0_131
export HADOOP_HOME=/hadoop/Hadoop/hadoop-3.1.2
export HADOOP_OS_TYPE=${HADOOP_OS_TYPE:-$(uname -s)}
#守护进程的日志文件的存储目录
export HADOOP_LOG_DIR=${HADOOP_HOME}/logs
#Hadoop PID文件的存放目录,内容为pid内容为进程号,这个最好是修改一下,因为/tmp目录通常来说是任何人都可以访问的,有可能存在符合链接攻击的风险。
export HADOOP_PID_DIR=/hadoop/Hadoop/hadoop-3.1.2/tmp

将log设置到HADOOP_HOME

5.2.3.5 其他

剩下的配置文件在Yarn和MapReduce章节讲述。

5.2.4 安装总结

安装的七个步骤:

1、启动journalnode守护进程;

ALL: hdfs --daemon start journalnode

2、需要和journalnode通讯,将格式化信息写入journalnode;

app-11: hdfs namenode –format

3、关闭所有守护进程journalnode;

ALL: hdfs --daemon stop journalnode

4、初始化zookeeper节点,生成hadoop-ha根目录;

app-11: hdfs zkfc -formatZK –force

5、启动整个dfs集群,也包括journalnode;

app-11: start-dfs.sh

6、在其他namenode上操作,将写到journalnode文件系统信息通过过来,后续namenode节点可以自动监控。因为在app-11上做第2步的时候,app-12节点还没有启动namenode进程,是在第5步之后才启动的namenode进程,之前的操作没有监控到。

app-12: hdfs namenode –bootstrapStandby

7、关闭dfs,通过start-all启动整个集群,不仅仅包括dfs,还包括yarn。

app-11: stop-dfs.sh && start-all.sh

这个流程是经过实践检验的正确步骤。

5.2.5 HDFS Federation/ViewFS

5.2.5.1 Federation

一个系统里面可能会存在多个HDFS的集群,前面提到NameNode负责整个集群所有文件的元数据信息的维护,随着文件系统的越来越庞大以及文件的越来越大,NameNode将不堪重负,为了应对这种情况,hadoop支持HDFS的水平方向扩展,将原来的单根目录下的集群方式变成多根目录下的集群方式,一部分NameNode负责一个根,另一部分负责另一个根,这样的话,将组建成一个大的文件系统,即Federation含义,和现实中的联邦制政府概念一样。

HDFS做Federation时,NameNode并没有改变,而是将NameNode的角色划分开来,比如说NN1或HA的NN1集合负责某一个根,但是其下面所支持的DataNode并没有改变,NN1集合负责维护本HDFS的namespace。

5.2.5.2 ViewFS

有了Federation后,如何管理这些子文件系统,可以将这些文件系统挂载在虚拟文件系统下,比如讲NS1的data目录挂载在/data目录下,形成一个虚拟文件系统,借助虚拟文件系统去管理整个由众多集群组成的大集群。

5.2.5.3 操作
5.2.5.3.1 启动集群

SSH连接app-11,切换到hadoop用户,启动集群

如果没有启动,则先启动zookeeper。然后启动整个hadoop环境;

/hadoop/tools/startZookeeper.sh
/hadoop/Hadoop/hadoop-3.1.2/sbin/start-all.sh
5.2.5.3.2 hdfs-site.xml

替换集群文件替换:/hadoop/Hadoop/hadoop-3.1.2/etc/Hadoop/hdfs-site.xml

修改内容,增加集群dm2

只有一个namenode在app-13上,服务于dm2,因为app-11和app-12已经有namenode做HA了,服务于dmcluster。

由于只剩下一台app-13,如何做Federation,使用了一个技巧,但是不建议。

<property>
	<name>dfs.ha.namenodes.dm2</name>
	<value>nn3</value>
</property>
<property>
	<name>dfs.client.failover.proxy.provider.dm2</name>
	<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
	<name>dfs.namenode.rpc-address.dm2.nn3</name>
	<value>app-13:8020</value>
</property>
<property>
	<name>dfs.namenode.http-address.dm2.nn3</name>
	<value>app-13:9870</value>
</property>

将文件拷贝到app-12和app-13

scp hdfs-site.xml hadoop@app-12:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/
scp hdfs-site.xml hadoop@app-13:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/
5.2.5.3.3 初始化namenode

由于使用app-13作为dm2的namenode,登录app-13:ssh hadoop@app-13

需要对namenode进行格式化

由于dm2集群只有一台namenode,却做了HA,这样格式化肯定会失败。

hdfs namenode -format -clusterId dm2

编辑vi hdfs-site.xml文件,注释掉

需要将dm2集群的namenode限制在app-13上,而不采用ha这种方式。

再次格式化:

hdfs namenode -format -clusterId dm2

启动namenode,运行namenode守护进程命令,这个命令只是启动本地的namenode

hdfs --daemon start namenode

相对于之前的app-13节点来说,增加了NameNode节点进程。

告诉datanode,已经有一个namenode启动了,他们需要将他们的数据库情况汇报给新的namenode,新的namespace。

hdfs dfsadmin -refreshNamenodes app-11:9867
hdfs dfsadmin -refreshNamenodes app-12:9867
hdfs dfsadmin -refreshNamenodes app-13:9867

其中端口号9867参考文档:Configuration-default.xlsx

关于端口介绍,用ipc方式和datanode交互。

到此为止dm2的namespace可以正常工作了。

5.2.5.3.4 管理虚拟文件

回到app-11,查看根目录:hdfs dfs -ls /

目前显示的输出为dmcluster的输出,想要获取dm2目录的输出,需要加前缀:

hdfs dfs -ls hdfs://dm2/

目前dm2的根目录没有内容。

在dm2创建文件夹:

hdfs dfs -mkdir hdfs://dm2/federation

dm2需要加是因为core-site.xml中定义的默认是dmcluster,而不是dm2,所以使用dm2需要手动加前缀。

类似于访问默认的可以这样访问:

hdfs dfs -ls hdfs://dmcluster/

修改core-site.xml文件,进行文件映射

<configuration>
	<property>
		<name>fs.defaultFS</name>
		<value>viewfs://ClusterX</value>
	</property>
	<property>
		<name>ha.zookeeper.quorum</name>
		<value>app-11:2181,app-12:2181,app-13:2181</value>
	</property>
	<property>
		<name>hadoop.tmp.dir</name>
		<value>/hadoop/Hadoop/hadoop-3.1.2/tmp</value>
	</property>

	<property>
		<name>fs.viewfs.mounttable.ClusterX.link./hadoop</name>
		<value>hdfs://dmcluster/hadoop</value>
	</property>
	<property>
		<name>fs.viewfs.mounttable.ClusterX.link./user</name>
		<value>hdfs://dmcluster/user</value>
	</property>
	<property>
		<name>fs.viewfs.mounttable.ClusterX.link./federation</name>
		<value>hdfs://dm2/federation</value>
	</property>
</configuration>

将该文件拷贝到app-12和app-13

scp core-site.xml hadoop@app-12:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/
scp core-site.xml hadoop@app-13:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/

无需重新启动集群,ViewFS就能生效

访问ViewFS的根,后两个文件夹是dmcluster集群内的目录。第一个目录是dm2里面的目录,从而有效管理整个集群。

新建的test和test2目录没有显示,是因为配置文件里面没有进行映射

5.2.5.3.5 复原

由于后续操作不需要Federation和ViewFS,将之前环境复原回去。

还原core-site.xml和hdfs-site.xml

同时覆盖app-12和app-13

scp hdfs-site.xml hadoop@app-12:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/
scp hdfs-site.xml hadoop@app-13:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/
scp core-site.xml hadoop@app-13:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/
scp core-site.xml hadoop@app-12:/hadoop/Hadoop/hadoop-3.1.2/etc/hadoop/

登录到app-11:ssh hadoop@app-13

停止namenode守护进程:hdfs –daemon stop namenode

至此,app-12节点的namenode以恢复。

关闭集群

发表回复