Hadoop切分纯文本时对某一行跨两个分片这种情况的处理

当我们提交一个MapReduce程序来处理一个或多个纯文本时,Hadoop会根据设置的分片(split)大小把文件切分成多个(InputSplit),然后分配给MapReduce程序处理。而由于Hadoop对文件做切分的时候,只考虑分片大小,而不管切分的时候会不会把某一行分成两半(事实上,一个分片的结尾正好是一个换行符的概率很低)。那么,在MapReduce程序处理每一行文本的时候,我们会不会得到一个不完整的行?
 
事实上,Hadoop对这种某一行跨两个分片的情况进行了特殊的处理。
通常Hadoop使用的InputSplit是FileSplit,一个FileSplit主要存储了三个信息<path, start, 分片length>。假设根据设置分片大小为100,那么一个250字节大小的文件切分之后,我们会得到如下的FileSplit:
<path, 0, 100>
<path, 100, 100>
<path, 200, 50>
(具体的切分算法可以参考 FileInputFormat的实现)
 
因此,事实上,每个MapReduce程序得到的只是类似<path, 0, 100>的信息。当MapReduce程序开始执行时,会根据path构建一个FSDataInputStream,定位到start,然后开始读取数据。在处理一个FileSplit的最后一行时,当读取到一个FileSplit的最后一个字符时,如果不是换行符,那么会继续读取下一个FileSplit的内容,直到读取到下一个FileSplit的第一个换行符。这样子就保证我们不会得到一个不完整的行了。
 
那么当MapReduce在处理下一个FileSplit的时候,怎么知道上一个FileSplit有没有已经处理了这个FileSplit的第一行内容?
我们只需要检查一下前一个FileSplit的最后一个字符是不是换行符,如果是,那么当前Split的第一行还没有被处理,如果不是,表示当前Split的第一行已经被处理,我们应该跳过。
LineRecordReader中,使用了一个很巧妙的方法来实现上述的逻辑,把当前FileSplit的start减一,然后跳过第一行(下面是这个代码片断)。
 
 
99
 
 
}else{
 
100
 
 
if(start!= 0) {
 
101
 
 
skipFirstLine =true;
 
102
 
 
--start;
 
103
 
 
fileIn.seek(start);
 
104
 
 
}
 
105
 
 
in=newLineReader(fileIn, job, recordDelimiter);
 
106
 
 
}
 
107
 
 
if(skipFirstLine) {// skip first line and re-establish &quot;start&quot;.
 
108
 
 
start+=in.readLine(newText(), 0,
 
109
 
 
(int)Math.min((long)Integer.MAX_VALUE,end-start));
 
110
 
 
}
 
事实上,InputSplit只是一个逻辑上的概念,跟HDFS本身的block等机制无关,HDFS的好处是让我们可以假设MapReduce程序只是在处理一个本地的文件。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值