众所周知,当将本地文本文件复制到HDFS时,该文件将被拆分为固定大小128 MB。例如,当我将256 MB文本文件复制到HDFS时,将有2个块(256/128)包含" splitted"文件。
有人可以告诉我 Hadoop 2.7.1 源代码中的哪个java / jar文件执行将文件拆分为块的功能以及哪个java / jar文件将块写入datanode&# 39; s目录。
帮我跟踪这段代码。
我只找到了他们为FileInputFormat.java中找到的块进行逻辑输入拆分的那个,这不是我需要的。我需要java文件来分割物理文件。
答案 0 :(得分:1)
将数据写入DataNode的代码存在于2个文件中:
# use fatal;
my $file = open 'nonexistent', :r;
say 'Reached here';
my @lines = $file.IO.lines;
(包裹:DFSOutputStream.java
)
客户端写入的数据被分成数据包(通常为64k大小)。当数据包准备就绪时,数据将被排入数据队列,由org.apache.hadoop.hdfs
获取。
DataStreamer
(包裹:DataStreamer
)
它获取数据队列中的数据包并将它们发送到管道中的数据节点(由于复制因子为3,数据管道中通常有3个数据节点)。
它检索新的块ID并开始将数据流式传输到数据节点。当写入一个数据块时,它会关闭当前块并获取一个用于写入下一组数据包的新块。
获取新块的代码如下:
org.apache.hadoop.hdfs
当前块关闭的代码如下:
// 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
如果写入的字节数等于blocksize:
,它还会继续检查/**
* 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
文件中的dfs.blocksize
参数确定(在我的群集中设置为128 MB = 134217728):
hdfs-site.xml
答案 1 :(得分:0)
它不是一个执行拆分文件功能的jar / java文件。它是执行此任务的客户端守护程序。当您从本地加载文件时,客户端首先只读取128MB,它通过询问namenode找到存储它的位置,并确保正确复制和复制该文件。此阶段的客户端不知道文件的实际大小,除非它以相同的方式读取所有块。
当您要存储文件时,hdfs不会使用您提到的FileInputFormat.java。当您要在该文件上运行任何mapreduce任务时使用它。它与文件存储无关。