在Hadoop的1.x版本中,NN的单点处理能力成为HDFS的主要(容量扩展/性能/可用性)瓶颈,主要表现在:一.NN在管理大规模的命名空间时,所消耗的内存堆必定在10GB/100GB级别,无论是触发的Full Gc(32GB需要2min)还是重启时(元数据加载/操作日志回放/数据块汇报)时间消耗对高可用性来说都是无可忍受的;二是NN在内部用一把全局锁撸遍所有的元数据操作来保证数据的一致性;三是被人一直诟病的NN单点故障问题; 所以从Hadoop的2.x开始,社区试图使用Federation+HA的方案来解决hadoop-1.x中的容量扩展及可用性的问题.本文将主要介绍这种方案的设计与实现,至于优劣并不做任何评价.
Federation方案的基本思路就是使用多个独立的NameSpace(NameNode节点管理)来满足HDFS命名空间的水平扩展,NameSpace之间在逻辑上是完全相互独立的(即任意两个NameSpace可以有完全相同的文件名),而在物理上可以完全独立(NameNode节点管理不同的DataNode)也可以有联系(共享存储节点DataNode)很显然,任何一个NameNode节点只能管理一个Namespace.这种在逻辑上无法统一命名空间的设计对于初学者来说,可能会常常踩到文件名冲突或文件不存在的陷阱中.很显然,任何一个NameNode节点只能管理一个Namespace.
HDFS-2.0 HA+Federation的总体设计
要实现NameNode的HA方案,最重要的部分就是需要一个共享式的存储系统来实时存储NameNode的操作日志,而这种共享式的存储系统必须要满足两个基本条件:一是自身必须要高可用,二是保证强一致性.目前,Hadoop-2.x使用Quorum Journal Manager(QJM)来实现操作日志的共享,QJM是一个比ZooKeeper要轻量级的分布式存储系统,所使用的一致性约束条件远远不如paxos,raft等高可用的一致性算法.HDFS抽象出了一个日志接口JournalManager来屏蔽底层对操作日志存储的实现细节,目前主要有三种实现:
+ JournalManager
-FileJournalManager
-QuorumJournalManager
-BackupJournalManager
FileJournalManager将操作日志写入本地文件系统中,QuorumJournalManager将操作日志写入QJM中来实现主/备NameNode之间的操作日志共享,BackupJournalManager将操作日志实时的推送给backup的NameNode节点.QuorumJournalManager为了保证性能,采用了异步并发的方式将操作日志刷入所有的JournalNode节点
配置的HA的HDFS,所有NameSpace的NameNode节点在启动加载完元数据之后都处于Standby状态,之后被手动或自动的选择一个NameNode节点作为Active节点而开始正常工作.HA的自动方式是通过在每一个NameNode的本地启动一个守护进程ZKFailoverController来竞争Active NameNode的,ZKFailoverController除了为本地的NameNode争取Active角色之外,还负责监控本地的NN节点当前是否正常的,一旦它发现本地的NN不正常,要么主动替当前的Active NN退出Active角色或退出Active的竞争.
一个DataNode既可以服务于一个NameSpace,也可以服务于多个NameSpace,它对HA+Federation方案的支持主要是通过BlockPoolManager来完成的.BlockPoolManager会给配置的所有NameSpace下的主/备NameNode节点都汇报块信息.
HDFS的HA方案并不只是保证NameNode节点的高可用,还得保证客户端能够对用户透明的容忍主/备NameNode节点之间的切换.目前客户端对HA方案的实现方式主要是通过重试的机制来完成的.