HDFS架构
Hadoop分布式文件系统(HDFS)是Hive存储数据的地方,简单了解HDFS的基本机制和读写工作机制,对于排查HiveSQL程序是否由于数据存储引发的性能问题有较大的帮助。
常见HDFS优化
常见的关于HDFS的优化角度有:
·Hive作业生成的小文件,过多的小文件会加重NameNode的负担,导致集群整体性能下降。
·设置合理的HDFS文件块的大小,可以减轻NameNode的负担,增加数据本地化操作的概率,提升程序性能。
·适当增大NameNode的Java堆,调整JVM的参数可以提升NameNode性能。
·在集群进行扩容和缩容的情况时,需要调整NameNode服务处理程序计数和NameNode处理程序计数。
·在HDFS写入大数据文件的时候,可以尝试启用写入后清理缓存,启用写入后立即对磁盘数据排队。
·在HDFS有比较多的随机读,或者一次性需要读取大数据文件时,可以启用读取后清理缓存。
·集群的单机性能较高,可以适当增大处理程序计数。
·HDFS在读取数据时会开启HDFS快速读取。
HDFS基本架构
HDFS基本架构
整个HDFS主要有3个组件:NameNode、DataNode和Client。
Client主要有以下几个职能:
·与NameNode进行交互,获取文件位置信息和文件块信息。
·与DataNode进行交互,读写数据文件。
·访问并管理HDFS集群。
常见的访问HDFS客户端方式有:
·命令行交互界面,在安装HDFS组件时自带。
·使用HttpFs服务,HttpFs提供Rest风格的操作接口,用于访问HDFS。
·访问NameNode提供的Web服务,默认端口是50070。
扩展:在获取文件存储块的位置时,通常会配置超时时间,减少作业因集群组件异常导致的作业长时间等待(配置项:dfs.client.file-block-storage-locations.timeout,dfs.client.file-block-storage-locations.timeout.millis)。
NameNode(NN)维护整个HDFS文件系统的目录树,以及目录树里的所有文件和目录,这些信息以两种文件存储在本地文件中:一种是NameSpace镜像(FSImage),即HDFS元数据些信息以两种文件存储在本地文件中:一种是NameSpace镜像(FSImage),即HDFS元数据的完整快照,每次NameNode启动时,默认加载最新的命名空间镜像;另一种是命名空间镜像的编辑日志(EditLog),它主要有几个职能:
管理HDFS的NameSpace,如打开、关闭重命名文件和目录。
·管理数据块与DataNode的映射关系。
·处理客户端的读写请求。
·管理副本的配置策略。
在较早的HDFS版本中还有一个关键组件:SecondaryNameNode(简称SNN)。SNN被设计用来辅助并分担NN的运行压力,主要用于定期合并命名空间镜像和命名空间镜像的编辑日志。NN在进行变更的时候会将变更操作到EditLog中,为了防止EditLog丢失及整个日志文件过大,在出现集群故障时,恢复成本大,需要定期将编辑日志进行归档,将编辑日志和整个NameSpace镜像文件进行合并。
NameNode为了防止日志读写及合并可能需要占用太多资源的情况,将这部分工作交给SNN。
DataNode节点(DN)的功能如下:
·处理客户端的读写请求。
·存储实际的数据。
·接收NameNode指令创建数据块。
查看当前DataNode整体信息,可以采用如下命令:
hdfs dfsadmin -report
通过上面的命令,可以快速查看当前HDFS存活节点的信息、磁盘使用情况信息及缓存使用情况信息等,通过这些信息,我们可以快速排除因节点不可用或磁盘空间不足引起的作业运行的异常。
HDFS的读流程
(1)Client先与NameNode进行交互,获取数据所在DataNode的地址和文件块信息。
(2)Client根据从NameNode得到的消息找到DataNode及对应的文件块,建立socket流。
(3)DataNode读取磁盘中的文件中回传给Client。
扩展:HDFS快速读取模式,Client会绕开DataNode自己去读取数据,实现方式是借助Linux操作系统中的Unix Domain Socket技术。在使用这个技术的时候要配置UNIX域套接字路径。当DataNode需要读取的数据非常大且读取后数据无法缓存到操作系统的缓存中时,通过配置属性——读取后清除缓冲区中的所有文件,可以提升其他作业的读取效率。
HDFS的写流程
(1)Client先与NameNode通信,表示要写入数据,NameNode会在NameSpace中添加一个新的空文件,并告知Client已经做好写的准备工作
(2)Client接到通知,向NameNode申请DataNode的数据块,NameNode会返回一个数据块,包含所有数据节点所在DataNode的位置信息。
(3)Client得到目标数据块位置,建立socket流,并向目标数据块写入数据。
HDFS高可用架构
在实际生产环境中,单个NameNode的HDFS集群基本不用,因为存在以下的情况:
·NameNode服务器或者NameNode本身出现异常,会导致整个HDFS集群不可用,从而导致Hive的程序出现异常。
·在运维人员维护NameNode服务器时,会导致整个HDFS集群不可用,从而导致所有Hive任务延期。
针对上面可能出现的问题,HDFS引入了高可用(High Availability,HA)特性,在同一个集群引入多NN用来解决上述问题,允许如果出现故障启用备用的NN节点,快速进行故障转移(failover)。当需要对集群的NN进行例行运维时,可以启用备用的节点,而不影响正常的线上生产。
HDFS提供了两种HA方案:NameNode HA With QJM与NameNode HA With NFS。第一种是业界较为主流的方案
HDFS HA架构
扩展:心跳指一个程序给另外一个程序周期性定时发送一个简单命令,以告知该程序还在运行,是存活的状态。
整个架构包含如下高可用设计:
1.NameNode服务的高可用设计
新增NN Standby节点。在HA集群中,要有两个或更多独立的机器节点被配置为Name Node。在任何时间点,恰好有一个NameNode处于活动状态,而其他的NN处于备用状态。活动NN负责集群中的所有客户端操作,而备用节点只是维护自己当前的状态和NN节点保持一致,以便在必要时提供快速故障转移。
2.JounalNode服务的高可用设计
新增一组JounalNode节点。为了让备用节点与活动节点保持同步状态,两个节点都与一组称为Journal Nodes(简称JNs)的独立守护进程通信。JNs是一个副本集,一般为3个副本,当有2个副本可以对外提供服务时,整个系统还处于可用状态。当活动节点执行任何的NameSpace内容修改时,它会持续地将修改记录写到这些JNs中。
备用节点能够从JNs读取日志,并不断监视它们对编辑日志的更改。当备用节点看到编辑时,会将它们应用到自己的名称空间。这样可确保在发生故障并在故障转移发生之前的两个NN状态完全同步。
3.服务存储状态的高可用设计
新增ZooKeeper(ZK)组件,使用多个副本用于存储HDFS集群服务状态信息。
4.故障转移控制服务的高可用设计
故障转移控制服务,发现监控的NN没有心跳,会尝试获取NN standy地址,并启动该服务,原先的standy状态变为active。但只有一个故障转移控制服务,如果不做高可用设计,也会出现单点问题,所以故障转移控制服务也被设计成支持服务的高可用。当工作的控制服务发生故障时,会启用备用的控制服务继续对集群提供服务。
扩展:上面的架构不管是在正常情况,还是异常发生在进行故障转移时,只允许一个NN处在工作状态,其他NN都处在备用(standy)状态。这是为避免两个NN同时工作时,两个NN的NameSpace状态将会出现差异,也就是“脑裂”现象,这可能导致数据丢失或其他错误结果。为了保证整个集群正常工作,JournalNodes只允许一个NameNode与它通信。在故障转移期间,变为活动工作状态的NameNode将接管向JournalNodes写入数据的角色。
NameNode联盟
在绝大多数的场景下,单个NameNode已经够用。我们来算一下:在NameNode创建一个数据块的元数据信息差不多占用500byte,在NameNode节点给予128GB的服务器,实际长期驻留内存设置为100GB,一个元数据对应的数据块大小给予设置256MB,则整个集群能够容纳的数据量是(100×1024^3/500)×256MB=51.2PB。大部分公司的数据都难以达到这个数据量级。
HDFS的NameNode高可用能够增强整个HDFS集群的可用性,保障系统即使在NameNode所在服务的服务器出现故障,也能通过启用其他服务器的NameNode继续对外提供服务。但是,当集群所管理的数据量逐渐增多时,单个NameNode服务所要占用的内存空间也会随着增多,这会带来几个问题:
·NameNode服务垃圾回收(GC)运行时间变长,导致NameNode对外响应效率变低。Hive提交任务大部分都需要访问NameNode服务,这会影响Hive的运行效率。
NameNode故障恢复时间变长或集群重启时间长。在进行故障恢复或重启时,单个NameNode需要将大量持久化在磁盘中的文件数据加载到内存中,并在内存构建出整个NameSpace目录树。
·内存无法一直持续扩展,Hadoop是运行在廉价的服务器集群上,内存资源有限。
针对上面的问题,HDFS提出了NameNode联盟架构方案。原先一个NameNode管理一个HDFS集群中的所有数据,现在将一个HDFS集群的数据划分给几个NameNode同时进行管理,这几个NameNode可以分布在不同的机器上,在对外提供服务时这几个NameNode采用同一的接口提供服务。通过这种方式解决单个NameNode无法管理一个大集群的问题。
HDFS基础架构简化图
整个HDFS由两部分组成:命名空间和块存储。
命名空间(NameSpace)由目录、文件和块组成。它支持所有与名称空间相关的文件系统操作,如创建、删除、修改和列出文件和目录。
块存储(Block storage)也由两部分组成:块管理和数据存储。DataNode提供本地文件系统数据存储和读写功能。块管理功能如下:
管理DataNode集群,通过周期心跳信息,或者DataNode主动注册动作来判定能够对外提供服务的DataNode节点。
·处理块信息并维护块的位置。
·支持块相关操作,如创建、删除、修改和查询块位置。
·管理块复制,并删除已过度复制的块。
Hadoop为了保证能够提供横向扩展的能力,在NameSpace这一层运行创建多个NameSpace,这几个NameSpace通过块的管理,实现共用DataNode的集群。几个NameNode之间的操作不互相影响,只是共用数据存储空间。
NameNode联盟
每个块池(block pool)都是由单独的NameSpace进行管理,每个Name Space对块的操作包括删除、创建,都是独立于其他NameSpace。当一个Namespace出现故障时不会影响其他NameSpace对外提供服务。每个NameSpace和其对应的块池被统称为一个NameSpace volumn,如果删除了DataNode或者NameSpace,则也会删除相应的块池。
NameNode联盟在一定程度上可以缓解单个NameNode的压力,但是在使用之前要对业务数据量有一个合理的预估和拆分,确保NameNode联盟中的单个NameNode的有足够资源满足需求。