Hadoop HDFS将哪个Java文件拆分为块
我们都知道,当本地的文本文件被复制到HDFS中时,该文件被分割成固定大小的128MB。例如,当我将一个256 MB的文本文件复制到HDFS中时,将有2个块(256/128)包含“拆分”的文件 有人能告诉我Hadoop 2.7.1源代码中的哪个java/jar文件具有将文件拆分为块的功能,哪个java/jar文件将块写入datanode目录 帮我追踪这段代码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文件 它不
我只找到了在FileInputFormat.java中为块进行逻辑输入拆分的那个,这不是我需要的。我需要被拆分的物理文件的java文件 它不是一个jar/java文件,它具有拆分文件的功能。执行此任务的是客户端守护进程。当您从本地加载文件时,客户机首先读取的数据仅为128MB,它通过询问namenode找到存储文件的位置,并确保文件被正确复制和复制。在此阶段,客户机不知道文件的实际大小,除非它将以相同的方式读取所有块
hdfs在存储文件时不使用您提到的FileInputFormat.java。当您要在该文件上运行任何mapreduce任务时,将使用该命令。它与文件的存储无关。将数据写入数据节点的代码存在于两个文件中:
(包: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(); }
// 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
共同实现这一点。一个创建数据包,另一个流传输数据包。两者共同工作以跟踪块边界,并根据需要获得新块。