赞
踩
发现了一个好文章,转给下方便自己看,大家最好去原文看。地址https://www.cnblogs.com/luengmingbiao/p/11235327.html
目录
3.3 SecondaryNamenode(辅助NameNode)
3.7 HDFS的高可用性(High Availability)
Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Apache Hadoop Core项目的一部分。
Hadoop 是Apache基金会下一个开源的分布式计算平台,它以分布式文件系统HDFS和MapReduce算法为核心,为用户提供了系统底层细节透明的分布式基础架构。用户可以在不了解分布式底层细节的情况下,充分利用分布式集群进行高速运算和存储。
Hadoop是一个能够让用户轻松架构和使用的分布式计算平台。它主要有以下几个优点:
①高可靠性。Hadoop按位存储和处理数据的能力值得人们信赖。
②高扩展性。Hadoop是在可用的计算机集簇间分配数据并完成计算任务的,这些集簇可以方便地扩展到数以千计的节点中。
③高效性。Hadoop能够在节点之间动态地移动数据,并保证各个节点的动态平衡,因此处理速度非常快。
④高容错性。Hadoop能够自动保存数据的多个副本,并且能够自动将失败的任务重新分配。
⑤低成本。与一体机、商用数据仓库以及QlikView、Yonghong Z-Suite等数据集市相比,Hadoop是开源的,项目的软件成本因此会大大降低。
缺点:
①不适合低延迟数据访问。
②无法高效存储大量小文件,会占用大量的namenode内存。
③不支持多用户写入以及任意修改文件。
HDFS以流式数据访问模式来存储超大文件,运行于商用硬件集群上。
以下是对HDFS的设计简单描述(详细可以参阅该文章):
HDFS采用master/slave架构。一个HDFS集群是有一个Namenode和一定数目的Datanode组成。Namenode是一个中心服务器,负责管理文件系统的namespace和客户端对文件的访问。Datanode在集群中一般是一个节点一个,负责管理节点上它们附带的存储。在内部,一个文件其实分成一个或多个block,这些block存储在Datanode集合里。Namenode执行文件系统的namespace操作,例如打开、关闭、重命名文件和目录,同时决定block到具体Datanode节点的映射。Datanode在Namenode的指挥下进行block的创建、删除和复制。Namenode和Datanode都是设计成可以跑在普通的廉价的运行Linux的机器上。HDFS采用java语言开发,因此可以部署在很大范围的机器上。一个典型的部署场景是一台机器跑一个单独的Namenode节点,集群中的其他机器各跑一个Datanode实例。这个架构并不排除一台机器上跑多个Datanode,不过这比较少见。集群中单一Namenode的结构大大简化了系统的架构。Namenode是所有HDFS元数据的仲裁者和管理者,这样,用户数据永远不会流过Namenode。
下图是Hadoop的架构设计图:
Hadoop的架构设计图
每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位。构建于单个磁盘之上的文件系统通过磁盘块来管理该文件系统中的块,该文件系统块的大小可以是磁盘块的整数倍。文件系统块一般为几千字节,而磁盘块一般为512字节。但这些对于需要读/写文件的文件系统用户来说是透明的。
HDFS同样也有块(block)的概念,但是大得多,默认为128MB。与单一磁盘上的文件系统相似,HDFS上的文件也被划分为块大小的多个分块,作为独立的存储单元。但与面向单一磁盘的文件系统不同的是,HDFS中小于一个块大小的文件不会占据整个块的空间,例如当一个1MB的文件存储在一个128MB的块中时,文件只使用1MB的磁盘空间,而不是128MB。
HDFS中的块为什么这么大?HDFS的块比磁盘的块大,其目的是为了最小化寻址开销。如果块足够大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。因为,传输一个由多个块组成的大文件的时间取决于磁盘传输速率。但是块大小这个参数也不会设置得过大,MapReduce中map任务通常一次只处理一个块中的数据,因此如果任务数太少(少于集群中的节点数量),作业的运行速度就会比较慢。
对分布式文件系统中的块进行抽象会带来很多好处。
HDFS将每个块复制到少数几个物理上相互独立的机器上(默认为3个),可以确保在块、磁盘或机器发生故障后数据不会丢失。如果发现一个块不可用,系统会从其他地方读取另一个复本,而这个过程对用户是透明的。一个因损坏或机器故障而丢失的块可以从其他候选地点复制到另一台可以正常运行的机器上,以保证复本的数量回到正常水平。同样,有些应用程序可能选择为一些常用的文件块设置更高的复本数量进而分散集群中的读取负载。
在HDFS中显示块信息:
# hdfs fsck / -files -blocks
可以执行命令修改HDFS的数据块大小以及复本数量:
# vim $HADOOP_HOME/etc/hadoop/hdfs-site.xml
3.2.1 NameNode目录结构
运行中的NameNode有如下所示的目录结构:
#Mon Sep 29 09:54:36 BST 2014 namespaceID=1342387246 clusterID=CID-01b5c398-959c-4ea8-aae6-1e0d9bd8b142 cTime=0 storageType=NAME_NODE blockpoolID=BP-526805057-127.0.0.1-1411980876842 layoutVersion=-57
编辑日志(edits log) :文件系统客户端执行写操作时,这些事务首先被记录到edits中。NameNode在内存中维护文件系统的元数据;当被修改时,相关元数据信息也同步更新。内存中的元数据可支持客户端的读请求。我们可以使用OEV查看edits文件:
选项解析:
-i,--inputFile <arg>:要处理的编辑文件 -o,--outputFile <arg>:输出文件的名称;如果指定的文件存在,它将被覆盖 -p,--processor <arg>:选择要应用于编辑文件的处理器类型 (XML|FileDistribution|Web|Delimited) oev中的e指定了镜像文件
命令如下:
<?xml version="1.0" encoding="UTF-8"?> <EDITS> <EDITS_VERSION>-63</EDITS_VERSION> <RECORD> <!-- 开始日志段--> <OPCODE>OP_START_LOG_SEGMENT</OPCODE> <DATA> <!-- 事务id--> <TXID>1</TXID> </DATA> </RECORD> <RECORD> <!-- 结束日志段--> <OPCODE>OP_END_LOG_SEGMENT</OPCODE> <DATA> <TXID>2</TXID> </DATA> </RECORD> </EDITS>
命名空间镜像文件(fsimage):文件系统元数据的持久检查点,每个fsimage文件包含文件系统中的所有目录和文件inode的序列化信息(从Hadoop-2.4.0起,FSImage开始采用Google Protobuf编码格式),每个inodes表征一个文件或目录的元数据信息以及文件的副本数、修改和访问时间等信息。数据块存储在DataNode中,但fsimage文件并不描述DataNode。我们可以使用OIV查看fsimage文件 :
选项解析:
-i,--inputFile <arg>:要处理的镜像文件 -o,--outputFile <arg>:输出文件的名称;如果指定的文件存在,它将被覆盖 -p,--processor <arg>:选择要应用于镜像文件的处理器类型 (XML|FileDistribution|Web|Delimited) oiv中的i指定了image文件
命令如下:
# hdfs oiv -p XML -i fsimage_0000000000000014026 -o fsimage.xml
View Code
seen_txid文件 :该文件对于NameNode非常重要,它是存放transactionId的文件,format之后是0,它代表的是NameNode里面的edits_*文件的尾数,NameNode重启的时候,会按照seen_txid的数字,循序从头跑edits_000*01~到seen_txid的数字。当hdfs发生异常重启的时候,一定要比对seen_txid内的数字是不是你edits最后的尾数,不然会发生建置NameNode时元数据信息缺失,导致误删DataNode上多余block。
in_use.lock文件 :是一个锁文件,NameNode使用该文件为存储目录加锁。可以避免其他NameNode实例同时使用(可能会破坏)同一个存储目录的情况。
3.2.2 NameNode的工作原理
NameNode管理文件系统的命名空间。它维护着文件系统树及整棵树内所有的文件和目录。这些信息以两个文件形式永久保存在本地磁盘上:命名空间镜像文件(fsimage)和编辑日志文件(edits log)。它也记录着每个文件中各个块所在的数据节点信息,但它并不永久保存块的位置信息,因为这些信息会在系统启动时根据DataNode节点信息重建,块信息存储在内存中。
可以看得出来NameNode的正常运行是非常重要的,如果运行的NameNode服务的机器毁坏,文件系统上所有的文件将会丢失,因为我们不知道如何根据DataNode的块重建文件。因此,Hadoop为此提供两种实现NameNode容错机制:
Hadoop SecondaryNameNode并不是Hadoop的第二个namanode,它不提供NameNode服务,而仅仅是NameNode的一个工具,这个工具帮助NameNode管理元数据信息。可能是由于SecondaryNameNode这个名字给人带来的混淆,Hadoop后面的版本(1.0.4)建议不要使用,而使用CheckPoint Node。但在这小节中,小编还是使用SecondaryNamenode。
运行中的SecondaryNamenode(辅助NameNode)的目录结构与主NameNode的目录结构几乎一样,但有部分时间不相同,它为主NameNode内存中的文件系统元数据创建检查点(后面解释)尚未成功时两者不相同。运行中的SecondaryNamenode有如下所示的目录结构:
当NameNode 启动时,需要合并fsimage和edits文件,按照edits文件内容将fsimage进行事务处理,从而得到HDFS的最新状态。实际应用中,NameNode很少重新启动。假如存在一个庞大的集群,且关于HDFS的操作相当频繁与复杂,那么就会产生一个非常大的edits文件用于记录操作,这就带来了以下问题:
此时,Secondary NameNode就要发挥它的作用了:合并edits文件,防止edits文件持续增长。该辅助NameNode会为主NameNode内存中的文件系统元数据创建检查点(fsimage文件),创建检查点前HDFS会自动进入安全模式(safe mode),当NameNode处在安全模式,管理员也可手动调用hdfs dfsadmin -saveNameSpace命令来创建检查点。创建检查点的步骤如下所示(如图中也简单地描述)。
创建检查点的步骤图
最终,主NameNode拥有最新的fsimage文件和一个更小的正在进行中的edits文件(edits文件可能非空,因为在创建检查点过程中主NameNode还可能收到一些编辑请求)。这个过程清晰解释了辅助NameNode和主NameNode拥有相近内存需求的原因(因为辅助NameNode也把fsimage文件载入内存)。因此,在大型集群中,辅助NameNode需要运行在一台专用机器上。
在hdfs-site.xml中可以配置与检查点触发点有关的属性:
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> <description>两个定期检查点之间的秒数 </description> </property> <property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>secondarynamenode或检查点节点将创建检查点 每个“dfs.namenode.checkpoint.txns”事务的名称空间 判断“dfs.namenode.checkpoint.period”是否已过期 </description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description>SecondaryNameNode和CheckpointNode将轮询NameNode 每隔'dfs.namenode.checkpoint.check.period'秒查询一次 未存入检查点事务 </description> </property>
默认情况下,辅助NameNode每隔一个小时创建检查点;此外,如果从上一个检查点开始编辑日志的大小已经达到100万个事务时,即使不到一小时,也会创建检查点,检查频率为每分钟一次。
这个过程namesecondary目录发生了更新;secondaryNameNode的检查点目录的布局与NameNode的是相同的,这种设计的好处是NameNode发生故障时,可以从secondaryNameNode恢复数据;有两种实现方法:一是将相关存储目录复制到新的NameNode中;二是使用-importCheckpoint选项启动NameNode守护进程,从而将secondaryNameNode用作新的NameNode
与第一次开启hdfs过程不同的是此次有30多秒的安全模式:
在安全模式中在等待块报告,这也关系到DataNode的运行过程。
DataNode是文件系统的工作节点。它们根据需要存储并检索数据块(受客户端或NameNode调度),并且定期向NameNode发送它们所存储的块的列表。
3.4.1 DataNode目录结构
和NameNode不同的是,DataNode的存储目录是初始阶段自动创建的,不需要额外格式化。DataNode的关键文件和目录如下所示:
分析:从上图可以看出,dataNode的文件结构主要由blk_前缀文件、BP-random integer-NameNode-IP address-creation time和VERSION构成。
注 :当目录中数据块的数量增加到一定规模时,DataNode会创建一个子目录来存放新的数据块及其元数据信息。如果当前目录已经存储了64个(通过dfs.datanode.numblocks属性设置)数据块时,就创建一个子目录。终极目标是设计一棵高扇出的目录树,即使文件系统中的块数量非常多,目录树的层数也不多。通过这种方式,DataNode可以有效管理各个目录中的文件,避免大多数操作系统遇到的管理难题,即很多(成千上万个)文件放在同一个目录之中。
#Mon Sep 29 09:54:36 BST 2014storageID=DS-c478e76c-fe1b-44c8-ba45-4e4d6d266547 clusterID=CID-01b5c398-959c-4ea8-aae6-1e0d9bd8b142 cTime=0 datanodeUuid=75ffabf0-813c-4798-9a91-e7b1a26ee6f1 storageType=DATA_NODE layoutVersion=-57
in_use.lock :
是一个锁文件,NameNode使用该文件为存储目录加锁。可以避免其他NameNode实例同时使用(可能会破坏)同一个存储目录的情况。
通常DataNode从磁盘中读取块,但对于访问频繁的文件,其对应的块可能被显式地缓存在DataNode内存中,以堆外块缓存(off-heap block cache)的形式存在。默认情况下,一个块仅缓存在一个DataNode的内存中,当然可以对每个文件配置DataNode的数量。作业调度器(用于MapReduce、Spark和其他框架的)通过在缓存块的DataNode上运行任务,可以利用块缓存的优势提高读操作的性能。
用户或应用通过在缓存池(cache pool)中增加一个 cache directive来告诉NameNode需要缓存哪些文件及存多久。缓存池是一个用于管理缓存权限和资源使用的管理性分组。
本小节只简单描述,有关HDFS的缓存管理请查阅官方文档或者其他等相关资料。
NameNode在内存中保存文件系统中每个文件和每个数据块的引用关系,这意味着对于一个拥有大量文件的超大集群来说,内存将成为限制系统横向扩展的瓶颈。在2.X发行版本系列中引入的联邦HDFS允许系统通过添加NameNode实现扩展,其中每个NameNode管理文件系统命名空间中的一部分。
在联邦环境中,每个NameNode维护一个命名空间卷(namespace volume),由命名空间的元数据和一个数据块池(block pool)组成,数据块池包含该命名空间下文件的所有数据块。命名空间卷之间是相互独立的,两两之间并不相互通信,甚至其中一个NameNode的失效也不会影响由其他NameNode维护的命名空间的可用性。
集群中的DataNode还需要注册到每个NameNode,并且存储着来自多个数据块池中的数据块。
联邦HDFS的架构图如下图所示:
联邦HDFS架构图
联邦HDFS更详细的请查阅官方文档。
通过联合使用在多个文件系统中备份NameNode的元数据和通过备用NameNode创建监测点能防止数据丢失,但是依旧无法实现文件系统的高可用性。NameNode依旧存在单点失效(SPOF)的问题。如果NameNode失效了,那么所有的客户端,包括MapReduce作业,均无法读、写或列举文件,因为NameNode是唯一存储元数据与文件到数据块映射的地方,对于一个大型并拥有大量文件和数据块的集群,NameNode的冷启动需要30分钟,甚至更长时间,系统恢复时间太长了,也会影响到日常维护。在这一情况下,Hadoop系统无法提供服务直到有新的NameNode上线。
在这样的情况下要向从一个失效的NameNode恢复,系统管理员得启动一个拥有文件系统元数据副本得新的NameNode,并配置DataNode和客户端以便使用这个新的NameNode。新的NameNode直到满足以下情形才能相应服务:
Hadoop2.X以上版本针对上述问题增加了对HDFS高可用性(HA)的支持。在这一实现中,配置了一对活动-备用(active-standby) NameNode。当活动NameNode失效,备用NameNode就会接管它的任务并开始服务于来自客户端的请求,不会有任何明显中断。实现这一目标需要在架构上做如下修改。HDFS HA架构图如下所示:
HDFS HA架构图
有两种高可用性共享存储可以做出选择:NFS过滤器或群体日志管理器(QJM, quorum journal manager)。QJM是一个专用的HDFS实现,为提供一个高可用的编辑日志而设计,被推荐用于大多数HDFS部署中,同时,QJM的实现并没使用Zookeeper,但在HDFS HA选取活动的NameNode时使用了Zookeeper技术。QJM以一组日志节点(journalnode)的形式运行,一般是奇数点结点组成,每个JournalNode对外有一个简易的RPC接口,以供NameNode读写EditLog到JN本地磁盘。当写EditLog时,NameNode会同时向所有JournalNode并行写文件,只要有N/2+1结点写成功则认为此次写操作成功,遵循Paxos协议。其内部实现框架如下:
QJM内部实现框架
从图中可看出,主要是涉及EditLog的不同管理对象和输出流对象,每种对象发挥着各自不同作用:
3.7.1 QJM写过程分析
上面提到EditLog,NameNode会把EditLog同时写到本地和JournalNode。写本地由配置中参数dfs.namenode.name.dir控制,写JN由参数dfs.namenode.shared.edits.dir控制,在写EditLog时会由两个不同的输出流来控制日志的写过程,分别为:EditLogFileOutputStream(本地输出流)和QuorumOutputStream(JN输出流)。写EditLog也不是直接写到磁盘中,为保证高吞吐,NameNode会分别为EditLogFileOutputStream和QuorumOutputStream定义两个同等大小的Buffer,大小大概是512KB,一个写Buffer(buffCurrent),一个同步Buffer(buffReady),这样可以一边写一边同步,所以EditLog是一个异步写过程,同时也是一个批量同步的过程,避免每写一笔就同步一次日志。
这个是怎么实现边写边同步的呢,这中间其实是有一个缓冲区交换的过程,即bufferCurrent和buffReady在达到条件时会触发交换,如bufferCurrent在达到阈值同时bufferReady的数据又同步完时,bufferReady数据会清空,同时会将bufferCurrent指针指向bufferReady以满足继续写,另外会将bufferReady指针指向bufferCurrent以提供继续同步EditLog。上面过程用流程图就是表示如下:
EditLog输出流程图
问题一:
既然EditLog是异步写的,怎么保证缓存中的数据不丢呢,其实这里虽然是异步,但实际所有日志都需要通过logSync同步成功后才会给client返回成功码,假设某一时刻NameNode不可用了,其内存中的数据其实是未同步成功的,所以client会认为这部分数据未写成功。还有EditLog怎么在多个JN上保持一致的呢?
解决方案:
1. 隔离双写
在ANN每次同步EditLog到JN时,先要保证不会有两个NN同时向JN同步日志,也就是说同一时间QJM仅允许一个NameNode向编辑日志中写入数据。这个隔离是怎么做的。这里面涉及一个很重要的概念Epoch Numbers,很多分布式系统都会用到。Epoch有如下几个特性:
但QJM是怎么保证上面的特性的呢,主要有以下几点:
这样就能保证主备NN发生切换时,就算同时向JN同步日志,也能保证日志不会写乱,因为发生切换后,原ANN的EpochNumber肯定是小于新ANN的EpochNumber,所以原ANN向JN的发起的所有同步请求都会拒绝,实现隔离功能,防止了脑裂。
2. 恢复in-process日志
如果在写过程中写失败了,可能各个JN上的EditLog的长度都不一样,需要在开始写之前将不一致的部分恢复。恢复机制如下:
3. 日志同步
日志从ANN同步到JN的过程,具体如下:
通过上面一些步骤,日志能保证成功同步到JN,同时保证JN日志的一致性,进而备NN上同步日志时也能保证数据是完整和一致的。
3.7.2 QJM读过程分析
这个读过程是面向备NN(SNN)的,SNN定期检查JournalNode上EditLog的变化,然后将EditLog拉回本地。SNN上有一个线程StandbyCheckpointer,会定期将SNN上FSImage和EditLog合并,并将合并完的FSImage文件传回主NN(ANN)上,就是所说的Checkpointing过程。下面我们来看下Checkpointing是怎么进行的。
在2.x版本中,已经将原来的由SecondaryNameNode主导的Checkpointing替换成由SNN主导的Checkpointing。下面是一个CheckPoint的流向图:
Checkpointing流向图
总的来说,就是在SNN上先检查前置条件,前置条件包括两个方面:距离上次Checkpointing的时间间隔和EditLog中事务条数限制。前置条件任何一个满足都会触发Checkpointing,然后SNN会将最新的NameSpace数据即SNN内存中当前状态的元数据保存到一个临时的fsimage文件( fsimage.ckpt)然后比对从JN上拉到的最新EditLog的事务ID,将fsimage.ckpt_中没有,EditLog中有的所有元数据修改记录合并一起并重命名成新的fsimage文件,同时生成一个md5文件。将最新的fsimage再通过HTTP请求传回ANN。通过定期合并fsimage有什么好处呢,主要有以下几个方面:
3.7.3 HDFS HA如何实现故障切换与规避?
在活动namenode(ANN)失效之后,备用namenode(SNN)能够快速(几十秒的时间)实现任务接管,因为最新的状态存储在内存中:包括最新的编辑日志条目和最新的数据块映射信息。实际观察到的失效时间略长一点(需要1分钟左右),这是因为系统需要保守确定活动namenode是否真的失效了。活动namenode失效且备用namenode也失效的情况下,当然这类情况发生的概率非常低非常低的,现在Hadoop 3.X发行版本已经支持运行更多备用namenode来提供更高的容错性。
系统中有一个称为故障转移控制器(failover controller)的新实体,管理着将活动namenode转移为备用namenode的转换过程。有多种故障转移控制器,但默认一种是使用了Zookeeper来确保有且仅有一个活动namenode。每一个namenode运行着一个轻量级的故障转移控制器,其工作就是监视宿主namenode是否失效(通过一个简单的心跳机制实现)并在namenode失效时进行故障转移,这就是HA的主备切换机制,主备选举依赖于Zookeeper。下面是主备切换的状态图:
Failover流程图
从图中可以看出,整个切换过程是由ZKFC(即故障转移控制器,全称Zookeeper Failover Controller)来控制的,具体又可分为HealthMonitor、ZKFailoverController和ActiveStandbyElector三个组件。
在故障切换期间,Zookeeper主要是发挥什么作用呢,有以下几点:
在哪些场景会触发自动切换呢,从HDFS-2185中归纳了以下几个场景:
管理员也可以通过手动发起故障转移,例如在进行日常维护时,这称为”平稳的故障转移“(graceful failover),因为故障转移控制器可以组织两个namenode有序地切换角色。命令参考如下所示。
// 将 active 状态由 nn1 切换到 nn2 # hdfs haadmin -failover --forcefence --forceactive nn1 nn2 // 在启用自动故障转移的集群上 --forcefence -- forceactive 参数不起作用 // 使用以下方法检查名称节点状态(假设 nn1 为 active,nn2 standby): # hdfs haadmin -getServiceState nn1 active # hdfs haadmin -getServiceState nn2 standby // 于是我们人为制造故障,在 nn1 上查看 NameNode 进程 # jps # kill -9 [进程ID] // 自动故障转移将会激活 nn2 节点,状态从 standby 转换为 active
但在非平稳故障转移的情况下,无法确切直到失效NameNode是否已经停止运行。例如网速较慢或者网络被分割的情况下,可能激发故障转移,但Active NameNode依然运行着并且依旧是Active NameNode。高可用实现做了更一步的优化,以确保先前Active NameNode不会执行危害系统并导致系统崩溃的操作,该方法称为”规避“。
规避机制包括:撤销NameNode访问共享存储目录的权限(通常使用供应商指定的NFS命令)、通过远程管理命令屏蔽相应的网络端口。最不行的话,可以通过“一枪爆头”(断电关机)等制造人为故障技术。
HDFS读数据流程图
HDFS读数据过程这一设计的一个重点是:客户端可以直接连接到DataNode检索数据,且NameNode告知客户端每个块所在的最佳DataNode,由于数据流分散在集群中的所有DataNode,所以这种设计能使HDFS扩展到大量的并发客户端。同时,NameNode只需要响应块位置的请求(这些信息存储在内存中,因而非常高效),无需响应数据请求,否则随着客户端数量的增长,NameNode会很快称为瓶颈。
这里HdfsDataInputStream是FSDataInputStream的子类,这里是通过子类创建父类对象。
HDFS写数据流程图
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。