在Hadoop1(版本<=0.22)中,由于NameNode和JobTracker存在单点中,这制约了hadoop的发展,当集群规模超过2000台时,NameNode和JobTracker已经不堪重负。于是,全新架构的hadoop2(版本>=0.23)诞生了,可以支持分布式NameNode、NameNode HA(NameNode High Available),实现了NameNode的横向扩展,使得集群规模最大可支持上万个节点。
1、Hadoop1局限性
NameNode存储用户HDFS文件的元数据信息,集群关闭时这些信息存放在磁盘上,但是在集群运行时,这些信息是加载在内存中的。由于在Hadoop1的架构中只存在一个NameNode和一个JobTracker,由此带来了一系列的局限性:
▶ NameNode无法扩展。随着文件数目的增大,NameNode节点压力也相应增大,当NameNode无法在内存中加载所有元数据信息的时候,集群的寿命就到头了;
▶ NameNode存在单点故障风险。所有的元数据信息存储在NameNode节点中,当此节点宕机或发生不可恢复的灾难时,集群的文件很难恢复;
▶ 存在文件访问权限控制的问题。一个NameNode对应一个NameSpace,所有用户的文件都处于同一NameSpace下,很难隔离,不利于HDFS在公有云环境下的应用;
▶ JobTracker存在单点故障风险。集群所有的任务都在JobTracker中执行,一旦此节点放生故障,所有执行的任务都会丢失。此外,JobTracker,也无法扩展,最多支持4000个并行任务;
2、Hadoop2的新特性
为了解决Hadoop1中存在的局限性,Hadoop2重新设计了框架架构,引入了许多新特性。
1) HDFS Federation
为了解决单点NameNode负载过重的问题,Hadoop2引入了HDFS联盟的概念。即多个HDFS同时存在,可支持更多的文件存储。每个HDFS存在一个激活的NameNode,每个NameNode对应一个NameSpace,配置人员可以选择合适的NameSpace划分方式,将所有的DataNode被全部的NameNode共享。DataNode中存储的数据有不同NameNode的标识,因此不同NameNode存储的数据不会混淆,这就好比某个部门内的员工同时服从于部门主管和人事主管管理,部门主管和人事主管管理的内容是不一样的,理论上不会发生冲突。系统提供了一个公共的Block pools隔离了NameSpace与Block交互,如图1.1和1.2所示。
图1.1 HDFS 联盟架构
图1.2 HDFS联盟架构
如果将一个城市中居住的市民比喻为HDFS中存储的文件,人才市场档案存储室的大小比喻为NameNode所在节点的内存大小,那么单点NameNode过重问题可以形象地比喻为:每一个市民都有档案保存在人才市场的房间中,当市民越来越多时,人才市场房间内的档案越来越多,一旦房间存满,那么即使整个城市还可以容纳更多的市民居住,也无法再添加更多的市民了,这时候整个城市容纳市民能力的瓶颈在于单个人才市场房间的存储能力。如果设置两个或多个人才市场来分担所有市民的档案,那么再也不用担心人才市场存放档案房间的大小了,当存放满时,可以再开一个新的人才市场用于存放档案,也即是说,此时整个城市容纳市民能力的瓶颈在于城市所有房间的居住能力和,能最大化地利用所有资源。
在HDFS联盟中,所有NameNode可以共享所有的DataNode,处于不同NameSpace下的文件会被系统很好的隔离,很好地实现了文件的访问权限控制。
2) Automatic High Available
为了规避单点NameNode存在的故障风险,Hadoop2支持自动HA的配置。NameNode就是整个集群的心脏,在Hadoop1时代,只存在一个NameNode,一旦该NameNode数据丢失或者不能工作,可能会给整个集群带来巨大的灾难。在Hadoop2中,可以支持一个集群内2个NameNode同时启动(目前是2个,以后会增加),其中一个处于active工作状态,另一个处于standby休眠状态。注意HA中的两个NameNode属于同一命名空间,这与HDFS联盟是不同的。两个NameNode为了数据同步,会通过一组称作JournalNodes的独立进程进行相互通信,其结果如图1.3所示。
图1.3 NameNode HA基本结构示意图
要实现集群的自动HA,通常都要依赖Zookeeper集群和ZFKC进程。ZKFC进程在NameNode所在的节点上启动,用于监测Active的NameNode进程是否处于可用状态,一旦发现Active的NameNode进程挂掉,就立即通知Zookeeper集群,然后standby的NameNode节点上的ZFKC进程就会执行命令,将standby的NameNode切换为Active状态。其工作原理示意图如1.4所示。
图1.4 NameNode自动HA系统结构示意图
需要注意的几点:
① 当active状态的NameNode宕机后,需要手动切换到standby状态的NameNode来继续提供服务。如果要实现自动切换,必须依赖Zookeeper;
② JournalNode进程非常轻量,可以部署在其他的服务器上。JournalNode节点个数至少为3个,且为奇数个,如3、5、7等。当运行N个节点时,系统可以容忍至少(N-1)/2个节点失败而不影响正常运行;
③ 配置了NameNode HA后,客户端可以通过HA的逻辑名称去访问数据,而不用指定某一台NameNode,当某一台NameNode失效自动切换后,客户端不必更改hdfs的连接地址,仍可通过逻辑名称去访问,需要在conf中添加如下设置:
conf.setStrings("dfs.nameservices", "cluster1,cluster2");
conf.setStrings("dfs.ha.namenodes.cluster1", "hadoop0,hadoop1");
conf.setStrings("dfs.namenode.rpc-address.cluster1.hadoop0", "hadoop0:9000");
conf.setStrings("dfs.namenode.rpc-address.cluster1.hadoop1", "hadoop1:9000");
//必须配置,可以通过该类获取当前处于active状态的namenode
conf.setStrings("dfs.client.failover.proxy.provider.cluster1", "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");