Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hadoop HDFS将哪个Java文件拆分为块_Java_Apache_Hadoop_Hdfs - Fatal编程技术网

Hadoop HDFS将哪个Java文件拆分为块

Hadoop HDFS将哪个Java文件拆分为块,java,apache,hadoop,hdfs,Java,Apache,Hadoop,Hdfs,我们都知道,当本地的文本文件被复制到HDFS中时,该文件被分割成固定大小的128MB。例如,当我将一个256 MB的文本文件复制到HDFS中时,将有2个块(256/128)包含“拆分”的文件 有人能告诉我Hadoop 2.7.1源代码中的哪个java/jar文件具有将文件拆分为块的功能,哪个java/jar文件将块写入datanode目录 帮我追踪这段代码 我只找到了在FileInputFormat.java中为块进行逻辑输入拆分的那个,这不是我需要的。我需要被拆分的物理文件的java文件 它不

我们都知道,当本地的文本文件被复制到HDFS中时,该文件被分割成固定大小的128MB。例如,当我将一个256 MB的文本文件复制到HDFS中时,将有2个块(256/128)包含“拆分”的文件

有人能告诉我Hadoop 2.7.1源代码中的哪个java/jar文件具有将文件拆分为块的功能,哪个java/jar文件将块写入datanode目录

帮我追踪这段代码


我只找到了在FileInputFormat.java中为块进行逻辑输入拆分的那个,这不是我需要的。我需要被拆分的物理文件的java文件

它不是一个jar/java文件,它具有拆分文件的功能。执行此任务的是客户端守护进程。当您从本地加载文件时,客户机首先读取的数据仅为128MB,它通过询问namenode找到存储文件的位置,并确保文件被正确复制和复制。在此阶段,客户机不知道文件的实际大小,除非它将以相同的方式读取所有块


hdfs在存储文件时不使用您提到的FileInputFormat.java。当您要在该文件上运行任何mapreduce任务时,将使用该命令。它与文件的存储无关。

将数据写入数据节点的代码存在于两个文件中:

  • DFSOutputStream.java
    (包:
    org.apache.hadoop.hdfs

    客户端写入的数据被分成数据包(通常为64k大小)。当一个数据包准备就绪时,数据将进入一个数据队列,该数据队列由
    DataStreamer
    拾取

  • DataStreamer
    (包:
    org.apache.hadoop.hdfs

    它拾取数据队列中的数据包并将其发送到管道中的数据节点(由于复制因子为3,数据管道中通常有3个数据节点)

    它检索一个新的块ID并开始将数据流传输到数据节点。当写入一个数据块时,它关闭当前块并获取一个新块以写入下一组数据包

    获取新块的代码如下所示:

    // get new block from namenode.
    if (stage == BlockConstructionStage.PIPELINE_SETUP_CREATE) {
      if(LOG.isDebugEnabled()) {
        LOG.debug("Allocating new block");
      }
      setPipeline(nextBlockOutputStream());
      initDataStreaming();
    }
    
    // Is this block full?
    if (one.isLastPacketInBlock()) {
      // wait for the close packet has been acked
      synchronized (dataQueue) {
        while (!shouldStop() && ackQueue.size() != 0) {
          dataQueue.wait(1000);// wait for acks to arrive from datanodes
        }
      }
      if (shouldStop()) {
        continue;
      }
    
      endBlock();
    }
    
    关闭当前块的代码如下所示:

    // get new block from namenode.
    if (stage == BlockConstructionStage.PIPELINE_SETUP_CREATE) {
      if(LOG.isDebugEnabled()) {
        LOG.debug("Allocating new block");
      }
      setPipeline(nextBlockOutputStream());
      initDataStreaming();
    }
    
    // Is this block full?
    if (one.isLastPacketInBlock()) {
      // wait for the close packet has been acked
      synchronized (dataQueue) {
        while (!shouldStop() && ackQueue.size() != 0) {
          dataQueue.wait(1000);// wait for acks to arrive from datanodes
        }
      }
      if (shouldStop()) {
        continue;
      }
    
      endBlock();
    }
    
    endBlock()
    方法中,阶段再次设置为:

    stage = BlockConstructionStage.PIPELINE_SETUP_CREATE;
    
    这意味着,将创建一个新管道,用于将下一组数据包写入新块

编辑:如何检测块的结尾?

由于
DataStreamer
不断向块追加数据,它会更新写入的字节数

/**
  * increase bytes of current block by len.
  *
  * @param len how many bytes to increase to current block
  */
void incBytesCurBlock(long len) {
    this.bytesCurBlock += len;
}
如果写入的字节数等于blocksize,它还会继续检查:

// If packet is full, enqueue it for transmission
//
if (currentPacket.getNumChunks() == currentPacket.getMaxChunks() ||
    getStreamer().getBytesCurBlock() == blockSize) {
  enqueueCurrentPacketFull();
}
在上面的语句中,以下条件检查是否达到块大小:

getStreamer().getBytesCurBlock() == blockSize)
如果遇到块边界,则调用
endBlock()
方法:

/**
 * if encountering a block boundary, send an empty packet to
 * indicate the end of block and reset bytesCurBlock.
 *
 * @throws IOException
 */
protected void endBlock() throws IOException {
    if (getStreamer().getBytesCurBlock() == blockSize) {
      setCurrentPacketToEmpty();
      enqueueCurrentPacket();
      getStreamer().setBytesCurBlock(0);
      lastFlushOffset = 0;
    }
}
这将确保关闭当前块,并从
Name节点
获取新块以写入数据

块大小由
hdfs site.xml
文件中的
dfs.blocksize
参数确定(在我的集群中设置为128 MB=134217728):


dfs.blocksize
134217728
新文件的默认块大小,以字节为单位。
您可以使用以下后缀(不区分大小写):k(kilo),
m(兆)、g(千兆)、t(兆)、p(千兆)、e(兆)来指定
尺寸(如128k、512m、1g等),或提供完整尺寸
以字节为单位(例如134217728表示128 MB)。

谢谢你的回答!但是“客户端守护进程任务”(您声称的)中肯定不应该有这样一个代码,即至少有一个if语句可以将数据从文件连续读取到一个块中,直到文件达到最大大小(128 MB)。这是一个非常好的答案,但是这个if语句if(one.islastpackeinblock()){}获取最大块大小的信息?代码的哪一部分表示要将文件拆分为128 MB?完美答案!为了确认,调用enqueueCurrentPacketFull()的if语句;在DFSOutputStream.java中,对吗?@Idris,是的,在
DFSOutputStream.java
中。
DFSOutputStream
DataStreamer
共同实现这一点。一个创建数据包,另一个流传输数据包。两者共同工作以跟踪块边界,并根据需要获得新块。