在hadoop中作为后端存储的文件系统HDFS发挥中重要的作用,HDFS是一个分布式文件系统,按照Google File System的思想开发的,针对的场景是低端服务器、写操作少而读操作多的情况。在HDFS中为了保证数据的完整和可靠,使用了多种方式,比如采用检验和(checksum)和多副本放置的策略,在HDFS中很常用的检验和方式采用的是CRC(循环冗余校验码)。HDFS是一种基于块的文件系统,采用的基本思想和ext文件系统的基本思想类似,只不过这是一个分布式文件系统。

下面是几个关于HDFS中重要的基本概念:

1、Block: 在HDFS中,每个文件都是采用的分块的方式存储,每个block放在不同的datanode上,每个block的标识是一个三元组(block id, numBytes,generationStamp),其中block id是具有唯一性,具体分配是由namenode节点设置,然后再由datanode上建立block文件,同时建立对应block meta文件(其中的内容,大部分是对应数据的检验和内容)。

2、Chunk:对应的中文名字也可以称为块,但是为了与block区分,还是称之为chunk。在DFSClient与DataNode之间通信的过程中,由于文件采用的是基于块的方式来进行的,但是在发送数据的过程中是以packet的方式来进行的,每个packet包含了多个chunk,同时对于每个chunk进行checksum计算,生成checksum bytes。

3、Packet:在DFSclient与DataNode之间通信的过程中,发送和接受数据过程都是以一个packet为基础的方式进行。

 关于HDFS中进行通信的数据包(Packet)的格式如下:

+-----------------------------------------------------------------------+
   |    4 byte packet length(exclude packet header)            | 
  +------------------------------------------------------------------------+
   |   8 byte offset in the block | 8 byte sequence number   |
  +------------------------------------------------------------------------+
   |                 1 byte isLastPacketInBlock                           |
  +------------------------------------------------------------------------+
  |                 4 byte Length of actual data                           |
 +-------------------------------------------------------------------------+
  |           x byte checksum data. x is defined below            |
 +-------------------------------------------------------------------------+
  |           actual data .........                                                  |
 +--------------------------------------------------------------------------+

x = (length of data + BYTE_PER_CHECKSUM - 1) / BYTE_PER_CHECKSUM * CHECKSUM_SIZE

在DFSclient与DataNode进行通信,采用的是经典的C/S结构。在DFSClient从DataNode节点上读取数据的过程中,比较中的几个数据类是FSDataInputStream、DFSDataInputStream、DFSinputStream。下面为HDFS中read的过程:

1、文件系统读操作read,获取的类型对象为FSDataInputStream,通过fs.open操作获得,对于具体的HDFS文件系统,则采用的是通过DFSDataInputStream进行具体操作,每次获取一个DFSDataInputStream时,通过包含DFSInputStream 来进行具体的HDFS文件系统读read操作。

2、通过建立DFSInputStream对象,采用预取的方式,从NameNode中获得多个文件块的位置信息(LocatedBlocks),然后在DFSClient端缓存这些Block位置信息

3、对于DFSclient发出的每次read操作,统一转换成的格式为read(byte[ ] buffer, int offset, int len)这种DFSInputStream对象的系统调用,在read操作中比较重要的两个方法为blockSeekTo(long pos)和readBuffer(byte[ ] buffer, int offset, int len),所有具体的操作都转换成这两种操作。

4、方法blockSeekTo(long pos)作用是定位到具体的DataNode上去,同时建立具体的BlockReader对象,因为HDFS采用了ShortCircuitRead的优化措施,所以对于本地的DataNode节点上的读取操作则创建的为BlockReaderLocal对象,而对于远端的DataNode则建立RemoteBlockReader对象进行接下来的操作。接下来重点介绍的是RemoteBlockReader对象与DataNode的交互过程。

5、在建立具体的BlockReader对象之后,通过readbuffer操作,使用blockreader对象的read方法进行数据的读取操作。

下面是RemoteBlockReader建立与DataNode之间的通信过程:

RemoteBlockReader与DataNode之间通信的协议过程:

  1、RemoteBlockReader端的通信:

a、RemoteBlockReader请求通信,通信头部格式如下:

+------------------------------------------------------+
|  2 byte DATA_TRANSFER_VERSION     |
+------------------------------------------------------+
|          1 byte OP_READ_BLOCK              |
+------------------------------------------------------+
|                8 byte BLOCK_ID                      |
+------------------------------------------------------+
|  8 byte BLOCK_GENERATION_STAMP |
+------------------------------------------------------+
|                8 byte startOffset                       |
+------------------------------------------------------+
|                  8 byte length                            |
+------------------------------------------------------+
|              text client_name                          |
+------------------------------------------------------+
|                        accessToken                     |
+------------------------------------------------------+

b、DataNode受到RemoteBlockReader的读取数据请求之后,发送响应信息,如果成功,则为OP_STATUS_SUCCESS。

c、接下来就是获取相应的检验和的类型checksum,同时在本地建立相应的checksum。DataNode返回具体的firstChunkOffset信息。

d、执行具体的read(byte[ ] buffer, int offset, int len)时,使用的是RemoteBlockReader的借口FSInputChecker里面的方法,通过检查,如果发现相应的buffer里面的data不存在的时候,则执行具体的readchunk操作,从DataNode中的BlockSender中读取相应的chunk数据信息,同时读取检验和,DataNode使用的是packet数据格式发送数据,在RemoteBlockReader读取数据后,进行checksum检查,如果发现不一致的情况,则向NameNode报告这个Block出现了问题,如果没有什么问题,则向DataNode报告检验和正常,当一个block读取完成后,DataNode上的BlockScanner就可以不用扫描这个Block,检查Block的完整信息。

2、DataNode端的通信:

a、DataNode上启动DataXceiverServer对象,用于侦听来自DFSclient或者其他DataNode上的连接请求,当有一个连接请求的时候建立一个DataXceiver对象为之服务

b、DataXceiver对象接受来自DFSClient端的请求头部,首先进行数据头部报文的识别。如果不是DATA_TRANSFER_VERSION类型,报告类型不匹配错误。然后读取DFSClient发送的读取的操作类型信息,如果是OP_READ_BLOCK,则执行readBlock()。

c、在DataNode端建立具体的BlockSender类型对象,这个对象用于具体的数据block发送操作,在DataNode端,从disk上读读取整个Block内核中去。在BlockSender中读取Block中使用了内核优化措施,调用NativeIO方法。在发送数据的时候也使用了内核优化措施,不用经过内核态-》用户态-》内核态的过程,有效的减少了时间。

以上大致就是HDFS中涉及到的Read过程。

HDFS的Read过程分析的更多相关文章

  1. HDFS读文件过程分析:读取文件的Block数据

    转自http://shiyanjun.cn/archives/962.html 我们可以从java.io.InputStream类中看到,抽象出一个read方法,用来读取已经打开的InputStrea ...

  2. HDFS写文件过程分析

    转自http://shiyanjun.cn/archives/942.html HDFS是一个分布式文件系统,在HDFS上写文件的过程与我们平时使用的单机文件系统非常不同,从宏观上来看,在HDFS文件 ...

  3. hdfs架构详解(防脑裂fencing机制值得学习)

    HDFS(Hadoop Distributed File System)是一个分布式文件存储系统,几乎是离线存储领域的标准解决方案(有能力自研的大厂列外),业内应用非常广泛.近段抽时间,看一下 HDF ...

  4. Hadoop日记Day11---主从节点接口分析

    一.NameNode 的接口分析 1. NameNode本质 经过前面的学习,可以知道NameNode 本身就是一个java 进程.观察RPC.getServer()方法的第一个参数,发现是this, ...

  5. HDFS的写数据过程分析

    HDFS的写数据过程分析 我们通过FileSystem类可以操控HDFS, 那我们就从这里开始分析写数据到HDFS的过程. 在我们向 HDFS 写文件的时候,调用的是 FileSystem.creat ...

  6. [HDFS_add_1] HDFS 启动过程分析

    0. 说明 HDFS 文件概念 && HDFS 启动过程分析 1. HDFS 文件概念 [1.1 NameNode 职能] 存储文件类型.大小.权限.路径等等元数据 通过 edits( ...

  7. HDFS的读数据过程分析

    我们继续在 FileSystem 类分析,读数据使用的是 open(-)方法,我们可以看到源码 FSDataInputStream in = fileSystem.open(new Path(&quo ...

  8. hadoop2.2原理:分析HDFS的文件读写

    File Read 程序举例: public class FileRead { public static void main(Sting[] args) throws Exception { Con ...

  9. 深入浅出Hadoop实战开发(HDFS实战图片、MapReduce、HBase实战微博、Hive应用)

    Hadoop是什么,为什么要学习Hadoop?     Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运 ...

随机推荐

  1. C#3.0匿名类和Lanmda表达式

    1.初始化器:className variableName = new className(property1=value1…); 2.var可以声明一个没有类型的变量,根据赋值的不同改变数据类型 3 ...

  2. Windows安装ActiveMQ记录

    1.下载压缩包(activeMQ应用要基于jdk服务上,安装本软件时,最好已经安装了jdk并且配置好了环境变量) 下载5.12.2版本:http://activemq.apache.org/activ ...

  3. java三元运算符

    由?:符号表示的,具体的含义其实就和if-else结构的含义差不多,这种运算符会将某个条件作两种处理,如果满足条件的话就执行第一个结果,如果不满足的话就执行另外一个结果,例如: Int A,B,C;  ...

  4. PHP两种实现无级递归分类的方法

    /** * 无级递归分类 TP框架 * @param int $assortPid 要查询分类的父级id * @param mixed $tag 上下级分类之间的分隔符 * @return strin ...

  5. centos7安装lua语言环境

    Linux 上安装 Lua 安装非常简单,只需要下载源码包并在终端解压编译即可. 官网地址:http://www.lua.org/download.html 我这里安装的是:lua-5.3.0.tar ...

  6. leetcode Ch3-DFS & Backtracking I

    一.树的遍历 [非递归版] 1. 后序 class Solution { public: vector<int> postorderTraversal(TreeNode *root) { ...

  7. Django中请求的生命周期 和 FBV模式和CBV模式

    Django的生命周期就是你的 一个请求所发生的整个流程 Django的生命周期内到底发生了什么呢?? . 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏 ...

  8. Shell使用手册

    1.循环数组 list=(20180531 20180430 20180331 20180228 20180131 20171231 20171130 20171031 20170930 201708 ...

  9. 乘风破浪:LeetCode真题_006_ZigZag Conversion

    乘风破浪:LeetCode真题_006_ZigZag Conversion 一.前言 到这里我们对基本的问题有了一定的理解,其中字符串的操作一直是一个比较困难的问题,这一点我们需要认真对待,采用合理的 ...

  10. 沉淀再出发:用python画各种图表

    沉淀再出发:用python画各种图表 一.前言 最近需要用python来做一些统计和画图,因此做一些笔记. 二.python画各种图表 2.1.使用turtle来画图 import turtle as ...