先说说Haoop HDFS 1.0的体系架构:
HDFS1.0体系架构总体图:
上面可以看到几个组件:
NameNode :
NameNode 是分布式文件系统的管理者, 主要负责文件系统的命名空间,集群配置信息与存储块的复制, NameNode 将Meta-data信息存储在内存中,Meta-Data包含文件信息,和每个文件块的信息,与每个文件块在哪个DataNode信息
Secondary NameNode:
辅助NameNode 不是 NameNode的热备,主要作用是分担NameNode工作量,定时合并fsimage和fsedits,推送给NameNode,紧急时可以帮助恢复NameNode,Editlog事务日志记录到fsedit ,根据Fsedit,更新印象文件fsimage(存储文件系统的命名空间,包含文件的映射与文件的属性等信息。
1)、fsimage文件其实是Hadoop文件系统元数据的一个永久性的检查点,其中包含Hadoop文件系统中的所有目录和文件idnode的序列化信息;
2)、edits文件存放的是Hadoop文件系统的所有更新操作的路径,文件系统客户端执行的所以写操作首先会被记录到edits文件中。
fsimage包含Hadoop文件系统中的所有目录和文件idnode的序列化信息;对于文件来说,包含的信息有修改时间、访问时间、块大小和组成一个文件块信息等;而对于目录来说,包含的信息主要有修改时间、访问控制权限等信息。fsimage并不包含DataNode的信息,而是包含DataNode上块的映射信息,并存放到内存中,当一个新的DataNode加入到集群中,DataNode都会向NameNode提供块的信息,而NameNode会定期的“索取”块的信息,以使得NameNode拥有最新的块映射。因为fsimage包含Hadoop文件系统中的所有目录和文件idnode的序列化信息,所以如果fsimage丢失或者损坏了,那么即使DataNode上有块的数据,但是我们没有文件到块的映射关系,我们也无法用DataNode上的数据!所以定期及时的备份fsimage和edits文件非常重要!
关于fsimage与Fsedit中的流程:
DataNode:
保存文件的基本信息,他将Block存储在文件系统中,保存了Block的Meta-data,并且定时将Meta-Data信息,发送给NameNode
Client:
与NameNode 交互获取文件位置信息,与DataNode交互,读取和写入文件。
文件写入:
1)Client向NameNode发起写请求,
2)NameNode根据文件大小和文件配置情况返回给Client部分DataNode信息
3)Client将文件划分成多个Bock ,根据DataNode的地址信息,按顺序写到每个DataNode中,
文件读取:
1)Client向NameNode发起读请求
2) NameNode返回DataNode信息
3)Client根据返回的信息去读取DataNode上数据信息。
总结:
Hadoop 1.x优点:
1)可以处理大文件 2)可以运行在廉价的集群上
缺点:
NameNode单点故障,SecondaryNode单点故障,不能恢复,这个风险非常大。其次NameNode内存受限不好扩展,因为HDFS1.0架构中只有一个NameNode,并且管理所有的DataNode。
Hadoop2.x 的系统架构:
Hadoop 2.X为了解决1.0 的单点故障问题,与内存受限问题在架构方面进行改进,使用方式不变。
Hadoop2.0采用了HA机制。 通过主备切换,解决NameNode单点故障问题
Hadoop2.0采用了HDFS Federation,水平扩展,支持多个NameNode,NameNode分管一些目录,
架构图如下:
可以看到 这个架构体系包含的几个组件:
1)对比HDFS1.x 没有Secondary NameNode组件了 JournalNodes替代了SecondaryNameNode,
2) 对比Hadoop1.0 HDFS2.x 多了 DFSZKFailoverController
3)还有就是有ZK
DFSZKFailoverController :
DFSZKFailoverController是Hadoop2.7中的一个核心组件,继承于ZKFailoverController
主要功能是在ZK上注册NameNode和监控NamaNode运行状态, NameNode古典后ZKFC为竞争锁,获得ZKFC的NameNode为Active其他为Standby
JournalNodes:
JournaNodes集群负责与Standy NameNode 和Active NameNode通讯 ,替代了HDFS1.x中Secondary NameNode的工作,NameNode 上所有的edit信息都会存储到JournalNode集群上,在JournalNode节点上Fsimage根据Edit新建进行合并,并且将新的fsimage发送给StandyNameNode和Active NameNode, 一旦Active NameNode出现异常,Standby NameNode会从Jouranl读取所有的Edit信息,然后切换成Active.
关于HDFS2.X fsimage与Fsedit的处理:
HA模式下的edit log文件会同时写入多个JournalNodes节点的
(1)、配置好HA后,客户端所有的更新操作将会写到JournalNodes节点的共享目录中,可以通过下面配置hdfs-site.xml
(2)、Active Namenode和Standby NameNode从JournalNodes的edits共享目录中同步edits到自己edits目录中;
(3)、Standby NameNode中的StandbyCheckpointer类会定期的检查合并的条件是否成立,如果成立会合并fsimage和edits文件;
(4)、Standby NameNode中的StandbyCheckpointer类合并完之后,将合并之后的fsimage上传到Active NameNode相应目录中;
(5)、Active NameNode接到最新的fsimage文件之后,将旧的fsimage和edits文件清理掉;
(6)、通过上面的几步,fsimage和edits文件就完成了合并,由于HA机制,会使得Standby NameNode和Active NameNode都拥有最新的fsimage和edits文件(之前Hadoop 1.x的SecondaryNameNode中的fsimage和edits不是最新的)
[html] view plain copy print?
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://XXXX/mycluster</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/export1/hadoop2x/dfs/journal</value>
</property>
查看NameNode edit fsimage 文件:
Hdfs-site.xml中
配置有current目录
查看Current目录:
为了解决NameNode可以水平扩展的问题:
Hadoop 2.x采用了
HDFS Federation
同时部署多个NameNode,这些NameNode之间是相互独立,也就是说他们不需要相互协调,DataNode同时在所有NameNode中注册,作为他们共有的存储节点,并定时向所有的这些NameNode发送心跳块使用情况的报告,并处理所有NameNode向其发送的指令。该架构如图2所示:
架构如下:
引入了两个概念 Bock Pool(存储块池)与ClusterID 集群ID
①一个Bock Pool 是块的集合,这些块属于一个单一的Namespace。DataNode存储着集群中所有Block Pool中的块。Block Pool的管理相互之间是独立的。这意味着一个Namespace可以独立的生成块ID,不需要与其他Namespace协调。一个NameNode失败不会导致Datanode的失败,这些Datanode还可以服务其他的Namenode。
一个Namespace和它的Block Pool一起称作命名空间向量(Namespace Volume)。这是一个自包含单元。当一个NameNode/Namespace删除后,对应的Block Pool也会被删除。当集群升级时,每个Namespace Volume也会升级。
②集群ID(ClusterID)的加入,是用于确认集群中所有的节点,也可以在格式化其它Namenode时指定集群ID,并使其加入到某个集群中。
(2)HDFS Federation与老HDFS架构的比较
①老HDFS架构只有一个命名空间(Namespace),它使用全部的块。而HDFS Federation 中有多个独立的命名空间(Namespace),并且每一个命名空间使用一个块池(block pool)。
②老HDFS架构中只有一组块。而HDFS Federation 中有多组独立的块。块池(block pool)就是属于同一个命名空间的一组块。
③老HDFS架构由一个Namenode和一组datanode组成。而HDFS Federation 由多个Namenode和一组Datanode,每一个Datanode会为多个块池(block pool)存储块。
看个配置文件就知道了Federation怎么配置了:
[html] view plain copy print?
集群c1的文件hdfs-site.xml
该文件只配置在hadoop101和hadoop102上。
<configuration> <property> <name>dfs.replication</name> <value>2</value> </property>
【指定DataNode存储block的副本数量。默认值是3个,我们现在有4个DataNode,该值不大于4即可。】
<property> <name>dfs.nameservices</name> <value>cluster1,cluster2</value> </property>
【使用federation时,使用了2个HDFS集群。这里抽象出两个NameService实际上就是给这2个HDFS集群起了个别名。名字可以随便起,相互不重复即可】
<property> <name>dfs.ha.namenodes.cluster1</name> <value>hadoop101,hadoop102</value> </property>
【指定NameService是cluster1时的namenode有哪些,这里的值也是逻辑名称,名字随便起,相互不重复即可】
<property> <name>dfs.namenode.rpc-address.cluster1.hadoop101</name> <value>hadoop101:9000</value> </property> 【指定hadoop101的RPC地址】 <property> <name>dfs.namenode.http-address.cluster1.hadoop101</name> <value>hadoop101:50070</value> </property> 【指定hadoop101的http地址】 <property> <name>dfs.namenode.rpc-address.cluster1.hadoop102</name> <value>hadoop102:9000</value> </property> 【指定hadoop102的RPC地址】 <property> <name>dfs.namenode.http-address.cluster1.hadoop102</name> <value>hadoop102:50070</value> </property> 【指定hadoop102的http地址】 <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop101:8485;hadoop102:8485;hadoop103:8485/cluster1</value> </property> 【指定cluster1的两个NameNode共享edits文件目录时,使用的JournalNode集群信息】 <property> <name>dfs.ha.automatic-failover.enabled.cluster1</name> <value>true</value> </property> 【指定cluster1是否启动自动故障恢复,即当NameNode出故障时,是否自动切换到另一台NameNode】 <property> <name>dfs.client.failover.proxy.provider.cluster1</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> 【指定cluster1出故障时,哪个实现类负责执行故障切换】 <property> <name>dfs.ha.namenodes.cluster2</name> <value>hadoop103,hadoop104</value> </property> 【指定NameService是cluster2时,两个NameNode是谁,这里是逻辑名称,不重复即可。以下配置与cluster1几乎全部相似,不再添加注释】 <property> <name>dfs.namenode.rpc-address.cluster2.hadoop103</name> <value>hadoop103:9000</value> </property> <property> <name>dfs.namenode.http-address.cluster2.hadoop103</name> <value>hadoop103:50070</value> </property> <property> <name>dfs.namenode.rpc-address.cluster2.hadoop104</name> <value>hadoop104:9000</value> </property> <property> <name>dfs.namenode.http-address.cluster2.hadoop104</name> <value>hadoop104:50070</value> </property> <!-- <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop101:8485;hadoop102:8485;hadoop103:8485/cluster2</value> </property>