一、开篇

Hadoop分布式文件系统(HDFS)是Hadoop大数据生态最底层的数据存储设施。因其具备了海量数据分布式存储能力,针对不同批处理业务的大吞吐数据计算承载力,使其综合复杂度要远远高于其他数据存储系统。

因此对Hadoop分布式文件系统(HDFS)的深入研究,了解其架构特征、读写流程、分区模式、高可用思想、数据存储规划等知识,对学习大数据技术大有裨益,尤其是面临开发生产环境时,能做到胸中有数。

本文重点从客户端读取HDFS数据的角度切入,通过Hadoop源代码跟踪手段,层层拨开,渐渐深入Hadoop机制内部,使其读取流程逐渐明朗化。

二、HDFS数据读取整体架构流程

如上图所示:描绘了客户端访问HDFS数据的简化后整体架构流程。

  • 客户端向hdfs namenode节点发送Path文件路径的数据访问的请求

  • Namenode会根据文件路径收集所有数据块(block)的位置信息,并根据数据块在文件中的先后顺序,按次序组成数据块定位集合(located blocks),回应给客户端

  • 客户端拿到数据块定位集合后,创建HDFS输入流,定位第一个数据块所在的位置,并读取datanode的数据流。之后根据读取偏移量定位下一个datanode并创建新的数据块读取数据流,以此类推,完成对HDFS文件的整个读取。

三、Hadoop源代码分析经过上述简单描述,我们对客户端读取HDFS文件数据有了一个整体上概念,那么这一节,我们开始从源代码跟踪的方向,深度去分析一下HDFS的数据访问内部机制。(一)  namenode代理类生成的源代码探索为什么我们要先从namenode代理生成说起呢?原因就是先了解清楚客户端与namenode之间的来龙去脉,再看之后的数据获取过程就有头绪了。

1. 首先我们先从一个hdfs-site.xml配置看起

dfs.client.failover.proxy.provider.fszx

org.apache.hadoop.hdfs.server.namenode.ha.

ConfiguredFailoverProxyProvider

配置中定义了namenode代理的提供者为ConfiguredFailoverProxyProvider。什么叫namenode代理?其实本质上就是连接namenode服务的客户端网络通讯对象,用于客户端和namenode服务端的交流。

2. 分析ConfiguredFailoverProxyProvider

上图是ConfiguredFailoverProxyProvider的继承关系,顶端接口是FailoverProxyProvider,它包含了一段代码:

/**

* Get the proxy object which should be used until the next failover event

* occurs.

* @return the proxy object to invoke methods upon

*/

public ProxyInfo getProxy();

这个方法返回的ProxyInfo就是namenode代理对象,当然客户端获取的ProxyInfo整个过程非常复杂,甚至还用到了动态代理,但本质上就是通过此接口拿到了namenode代理。

3. 此时类关系演化成如下图所示:

上图ProxyInfo就是namenode的代理类,继承的子类NNProxyInfo就是具体指定是高可用代理类。

4. 那么费了这么大劲搞清楚的namenode代理,它的作用在哪里呢?

这就需要关注一个极为重要的对象DFSClient了,它是所有客户端向HDFS发起输入输出流的起点,如下图所示:上图实线代表了真实的调用过程,虚线代表了对象之间的间接关系。我们可以看到DFSClient是一个关键角色,它由分布式文件系统对象(DistributeFileSystem)初始化,并在初始化中调用NameNodeProxiesClient等一系列操作,实现了高可用NNproxyInfo对象创建,也就是namenode代理,并最终作为DFSClient对象的一个成员,在创建数据流等过程中使用。(二)  读取文件流的深入源代码探索

1. 首先方法一样,先找一个切入口。建立从HDFS下载文件到本地的一个简单场景,以下是代码片段

……

//打开HDFS文件输入流

input = fileSystem.open(new Path(hdfs_file_path));

//创建本地文件输出流

output = new FileOutputStream(local_file_path);

//通过IOUtils工具实现数据流字节循环复制

IOUtils.copyBytes(input, output, 4096, true);

……

咱们再看看IOUtils的一段文件流读写的方法代码。

/**

* Copies from one stream to another.

*

* @param in InputStrem to read from

* @param out OutputStream to write to

* @param buffSize the size of the buffer

*/

public static void copyBytes(InputStream in, OutputStream out, int buffSize)

throws IOException {

PrintStream ps = out instanceof PrintStream ?

(PrintStream)out : null;

byte buf[] = new byte[buffSize];

int bytesRead = in.read(buf);

while (bytesRead >= 0) {

out.write(buf, 0, bytesRead);

if ((ps != null) && ps.checkError()) {

throw new IOException("

Unable to write to output stream.");

}

bytesRead = in.read(buf);

}

}

这段代码是个标准的循环读取HDFS InputStream数据流,然后向本地文件OutputStream输出流写数据的过程。我们的目标是深入到HDFS InputStream数据流的创建和使用过程。

2. 接下来我们开始分析InputStream的产生过程,如下图所示:

上图实线代表了真实的调用过程,虚线代表了对象之间的间接关系。其代码内部结构极为复杂,我用此图用最简化的方式让我们能快速的理解清楚他的原理。我来简单讲解一下这个过程:

  • 第一步 

是DistributeFileSystem通过调用DFSClient对象的open方法,实现对DFSInputStream对象的创建,DFSInputStream对象是真正读取数据块(LocationBlock)以及与datanode交互的实现逻辑,是真正的核心类。

  • 第二步 

DFSClient在创建DFSInputStream的过程中,需要为其传入调用namenode代理而返回的数据块集合(LocationBlocks)。

  • 第三步

DFSClient创建一个装饰器类HDFSDataInputStream,封装了DFSInputStream,由装饰器的父类FSDataInputStream最终返回给DistributeFileSystem,由客户端开发者使用。

3. 最后我们再深入到数据块读取机制的源代码上看看,如下图所示:

上图实线代表了真实的调用过程,虚线代表了对象之间的间接关系。实际的代码逻辑比较复杂,此图也是尽量简化展现,方便我们理解。一样的,我来简单讲解一下这个过程:

  • 第一步 

FSDataInputStream装饰器接受客户端的读取调用对DFSInputStream对象进行read(...)方法调用。

  • 第二步 

DFSInputStream会调用自身的blockSeekTo(long offset)方法,一方面根据offset数据偏移量,定位当前是否要读取新的数据块(LocationBlock),另一方面新的数据块从数据块集合(LocationBlocks)中找到后,寻找最佳的数据节点,也就是Hadoop所谓的就近原则,先看看本机数据节点有没有副本,再次根据网络距离着就近获取副本。

  • 第三步 

通过FSDataInputStream副本上数据块(LocationBlock)构建BlockReader对象,它就是真正读取数据块的对象。BlockReader对象它有不同的实现,由BlockReaderFactory.build根据条件最优选择具体实现,BlockReaderLocal和BlockReaderLocalLegacy(based on HDFS-2246)是优选方案,也是short-circuit block readers方案,相当于直接从本地文件系统读数据了,若short-circuit因为安全等因素不可用,就会尝试UNIX domain sockets的优化方案,再不行才考虑BlockReaderRemote建立TCP sockets的连接方案了。BlockReader的细节原理也非常值得深入一探究竟,下次我专门写一篇针对BlockReader原理机制文章。四、结束非常感觉您能看完。下一篇我会对“Hadoop分布式文件系统(HDFS)数据写入流程”做一篇深度探索分析。期盼您的关注。

hdfs读写流程_深度探索Hadoop分布式文件系统(HDFS)数据读取流程相关推荐

  1. 大数据技术之Hadoop分布式文件系统HDFS系统知识整理(从入门到熟练操作)

    系列博客 1.大数据技术之Hadoop完全分布式集群搭建+Centos7配置连通外网和主机 2.大数据技术之Hadoop编译源码 3.大数据技术之Hadoop分布式文件系统HDFS系统知识整理(从入门 ...

  2. Hadoop分布式文件系统HDFS的工作原理详述

    Hadoop分布式文件系统(HDFS)是一种被设计成适合运行在通用硬件上的分布式文件系统.HDFS是一个高度容错性的系统,适合部署在廉价的机器上.它能提供高吞吐量的数据访问,非常适合大规模数据集上的应 ...

  3. JAVA大数据(二) Hadoop 分布式文件系统HDFS 架构,MapReduce介绍,Yarn资源调度

    文章目录 1.分布式文件系统HDFS 1.HDFS的来源 2.HDFS的架构图之基础架构 2.1 master/slave 架构 2.2 名字空间(NameSpace) 2.3 文件操作 2.4副本机 ...

  4. Hadoop分布式文件系统 (HDFS)

    Hadoop分布式文件系统 简介 ​ HDFS(Hadoop distribute file system) 是Hadoop核心组成,是分布式存储服务 ​ 分布式文件系统能够横跨多态计算机.在大数据时 ...

  5. Hadoop分布式文件系统--HDFS结构分析

    前言 在Hadoop内部,详细实现了很多类的文件系统,当然最最被我们用到的就是他的分布式文件系统HDFS了. 可是本篇文章不会讲HDFS的主从架构等东西,由于这些东西网上和资料书中都讲得非常多了. 所 ...

  6. Hadoop 分布式文件系统 - HDFS

    当数据集超过一个单独的物理计算机的存储能力时,便有必要将它分不到多个独立的计算机上.管理着跨计算机网络存储的文件系统称为分布式文件系统.Hadoop 的分布式文件系统称为 HDFS,它 是为 以流式数 ...

  7. Hadoop分布式文件系统HDFS

    HDFS的探究: HDFS HDFS是 Hadoop Distribute File System的缩写,是谷歌GFS分布式文件系统的开源实现,Apache Hadoop的一个子项目,HDFS基于流数 ...

  8. Hadoop分布式文件系统——HDFS

    一.介绍 HDFS (Hadoop Distributed File System)是 Hadoop 下的分布式文件系统,具有高容错.高吞吐量等特性,可以部署在低成本的硬件上. 二.HDFS 设计原理 ...

  9. Hadoop分布式文件系统——HDFS原理简介

    阅读前必看 这篇文章与其说是一篇文章,不如说是一篇在家学习的笔记,其中大部分内容来自于github上一个大神的开源笔记,在此附上链接,表达版权所属以及敬意:github源地址 一.介绍 HDFS(Ha ...

最新文章

  1. Linux---管理网络
  2. linux sudo 实现原理
  3. 学习javascript数据结构(三)——集合
  4. 机房运维很枯燥?来看看中国银行数据中心基础设施可视化运维管理
  5. Anaconda日志
  6. Axure教程 axure新手入门基础(3) 简单易上手
  7. 查看VMware上虚拟机的 ip 地址
  8. loss下降auc下降_梯度下降算法 线性回归拟合(附Python/Matlab/Julia源代码)
  9. uniapp+typeScript+vue3.0+vite
  10. 碰撞检测技术:kd tree
  11. 超9000万LoRa节点,全球物联网的事实标准已形成?
  12. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_07 缓冲流_5_BufferedWriter_字符缓冲输出流...
  13. spark学习7之IDEA下搭建Spark本地编译环境并上传到集群运行
  14. Python Pymysql实现数据存储
  15. html鼠标移动自动展开,JS实现鼠标滑过折叠与展开菜单效果代码
  16. 怎么在线给pdf加盖电子公章
  17. Java SE菜鸟之泛型
  18. 知乎点赞过万留学生自述:我们为什么需要代写???
  19. 【二分查找】详细图解
  20. 10.0 自定义SystemUI下拉状态栏和通知栏视图(八)之锁屏通知布局

热门文章

  1. java 延迟初始化_Java并发编程——延迟初始化占位类模式
  2. 正则表达式的非捕获性分组
  3. Java Web工程结构_项目结构
  4. 包包各部位名称图解_品尝烤肉必备!日本和牛各部位名称中日翻译对照 点餐更轻松...
  5. 表必须要有主键吗_玄关隔断什么材质好?玄关隔断必须要做吗?
  6. outlook邮箱邮件大小限制_设置Office 365邮箱默认发送和接收邮件大小限制
  7. python 实现语音转文字_python3实现语音转文字(语音识别)和文字转语音(语音合成)...
  8. zynq+linux固化程序,如何在 Zynq UltraScale+ MPSoC 上实现 Linux UIO 设计
  9. 26条C++的经典语录,哪几句戳中你的心!
  10. C语言项目:绽放的玫瑰花