簡體   English   中英

Hadoop HDFS文件拆分為哪些Java文件

[英]Which Java file does Hadoop HDFS file splitting into Blocks

眾所周知,當將本地文本文件復制到HDFS時,該文件將被拆分為固定大小的128 MB。 例如,當我將256 MB的文本文件復制到HDFS中時,將有2個塊(256/128)包含“分割的”文件。

有人可以告訴我Hadoop 2.7.1源代碼中的哪個java / jar文件執行將文件拆分為塊的功能,以及哪個java / jar文件將這些塊寫入datanode的目錄中。

幫我追蹤這段代碼。

我只找到了他們對FileInputFormat.java中找到的塊進行邏輯輸入拆分的地方,這不是我所需要的。 我需要將Java文件用於拆分的物理文件。

將數據寫入DataNodes的代碼位於2個文件中:

  • 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(); } 

    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;
}

它還繼續檢查是否寫入的字節數等於塊大小:

// 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 Node獲得一個新塊以寫入數據。

塊大小由hdfs-site.xml文件中的dfs.blocksize參數確定(在我的集群中設置為128 MB = 134217728):

<property>
    <name>dfs.blocksize</name>
    <value>134217728</value>
    <description>The default block size for new files, in bytes.
        You can use the following suffix (case insensitive): k(kilo),
        m(mega), g(giga), t(tera), p(peta), e(exa) to specify the
        size (such as 128k, 512m, 1g, etc.), Or provide complete size
        in bytes (such as 134217728 for 128 MB).
    </description>
</property>

它不是一個jar / java文件,它具有拆分文件的功能。 客戶端守護程序執行此任務。 當您從本地加載文件時,客戶端僅讀取128MB,它通過詢問namenode來找到一個存儲位置,並且還可以確保文件已正確復制和復制。 客戶端在此階段不知道文件的實際大小,除非它要以相同的方式讀取所有塊。

當您要存儲文件時,hdfs不會使用您提到的FileInputFormat.java。 當您要在該文件上運行任何mapreduce任務時使用它。 它與文件的存儲無關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM