MapReduce中FileInputFormat解析

1、概述

在map阶段,文件先被切分成split块,而后每一个split切片对应一个Mapper任务。
FileInputFormat这个类先对输入文件进行逻辑上的划分,以128M为单位,将原始数据从逻辑上分割成若干个split,每个split切片对应一个Mapper任务。

2、切片与与MapTask并行度决定机制

数据块:Block 是 HDFS 物理上把数据分成一块一块。数据块是 HDFS 存储数据单位。
数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行
存储。数据切片是MapReduce程序计算输入数据的单位,一个切片会对应启动一个MapTask。
在这里插入图片描述

3、FileInputFormat切片源码解析

(1)程序先找到你数据存储的目录。
(2)开始遍历处理(规划切片)目录下的每一个文件
(3)遍历第一个文件ss.txt
       a)获取文件大小fs.sizeOf(ss.txt)
       b)计算切片大小
       computeSplitSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
       c)默认情况下,切片大小=blocksize
       d)开始切,形成第1个切片:ss.txt—0:128M 第2个切片ss.txt—128:256M 第3个切片ss.txt—256M:300M
       (每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片
       e)将切片信息写到一个切片规划文件中
       f)整个切片的核心过程在getSplit()方法中完成
       g)InputSplit只记录了切片的元数据信息,比如起始位置、长度以及所在的节点列表等。
(4)提交切片规划文件到YARN上,YARN上的MrAppMaster就可以根据切片规划文件计算开启MapTask个数

4、FileInputFormat切片机制

(1)切片机制
       ① 简单地按照文件的内容长度进行切片
       ② 切片大小,默认等于Block大小
       ③ 切片时不考虑数据集整体,而是逐个针对每一个文件单独切片

(2)案例分析
       ① 输入数据有两个文件:
       file1.txt 320M
       file2.txt 10M
       ② 经过FileInputFormat的切片机制。运算后,形成的切片信息如下:
       file1.txt.split1-- 0~128
       file1.txt.split2-- 128~256
       file1.txt.split3-- 256~320
       file2.txt.split1-- 0~10M

5、FileInputFormat切片大小的参数配置

(1)源码中计算切片大小的公式
Math.max(minSize, Math.min(maxSize, blockSize));
mapreduce.input.fileinputformat.split.minsize=1 默认值为1
mapreduce.input.fileinputformat.split.maxsize= Long.MAXValue 默认值Long.MAXValue
因此,默认情况下,切片大小=blocksize。
(2)切片大小设置
maxsize(切片最大值):参数如果调得比blockSize小,则会让切片变小,而且就等于配置的这个参数的值。
minsize(切片最小值):参数调的比blockSize大,则可以让切片变得比blockSize还大。
(3)获取切片信息API
// 获取切片的文件名称
String name = inputSplit.getPath().getName();
// 根据文件类型获取切片信息
FileSplit inputSplit = (FileSplit) context.getInputSplit();

6、FileInputFormat实现类

在运行 MapReduce 程序时,输入的文件格式包括:基于行的日志文件、二进制格式文件、数据库表等。那么,针对不同的数据类型,MapReduce 是如何读取这些数据的呢?
FileInputFormat 常见的接口实现类包括:TextInputFormat、KeyValueTextInputFormat、
NLineInputFormat、CombineTextInputFormat 和自定义 InputFormat
等。

(1)TextInputFormat
TextInputFormat 是默认的 FileInputFormat 实现类。按行读取每条记录。键是存储该行在整个文件中的起始字节偏移量, LongWritable 类型。值是这行的内容,不包括任何行终止符(换行符和回车符),Text 类型。
以下是一个示例,比如,一个分片包含了如下 4 条文本记录。

Rich learning form
Intelligent learning engine
Learning more convenient
From the real demand for more close to the enterprise

每条记录表示为以下键/值对:

(0,Rich learning form)
(20,Intelligent learning engine)
(49,Learning more convenient)
(74,From the real demand for more close to the enterprise)

(2)CombineTextInputFormat

CombineTextInputFormat切片机制:
框架默认的 TextInputFormat 切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个 MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
1 ) 应用场景:
CombineTextInputFormat 用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个 MapTask 处理。

2 ) 虚拟存储切片最大值设置
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值。

3 ) 切片机制
生成切片过程包括:虚拟存储过程和切片过程二部分。

CombineTextInputFormat具体过程:
在这里插入图片描述
1)虚拟存储过程:
将输入目录下所有文件大小,依次和设置的 setMaxInputSplitSize 值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值 2 倍,此时将文件均分成 2 个虚拟存储块(防止出现太小切片)。
例如 setMaxInputSplitSize 值为 4M,输入文件大小为 8.02M,则先逻辑上分成一个4M。剩余的大小为 4.02M,如果按照 4M 逻辑划分,就会出现 0.02M 的小的虚拟存储文件,所以将剩余的 4.02M 文件切分成(2.01M 和 2.01M)两个文件。

2)切片过程:
(a)判断虚拟存储的文件大小是否大于 setMaxInputSplitSize 值,大于等于则单独形成一个切片。
(b)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
(c)测试举例:有 4 个小文件大小分别为 1.7M、5.1M、3.4M 以及 6.8M 这四个小文件,则虚拟存储之后形成 6 个文件块,大小分别为:

1.7M,(2.55M、2.55M),3.4M 以及(3.4M、3.4M)

最终会形成 3 个切片,大小分别为:

(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MapReduce是一种分布式计算框架,可以方便地处理大规模数据集。在HadoopMapReduce被广泛应用于数据处理和分析。下面是一个基于MapReduce的文件合并和去重的实现方法。 假设我们有一批文本文件需要合并,并且这些文件可能包含重复的数据记录。我们需要使用MapReduce来实现这个任务。 首先,我们需要定义MapReduce的输入和输出格式。对于输入,我们将每个文件作为一个输入记录,并将文件的内容作为值。对于输出,我们将每个不重复的记录作为一个输出记录,并将记录的内容作为值。 接下来,我们需要实现Map和Reduce函数。Map函数将每个输入记录解析为多个数据记录,并将它们映射到键-值对。对于我们的文件合并和去重任务,我们可以使用文件的每一行作为一个输入记录,并将行内容作为值。在Map函数,我们将每个行内容作为键,并将一个固定的值作为值。这样,Map函数将为每个不同的行内容生成一个键-值对。 Reduce函数将相同键的所有值合并为一个输出记录,并将输出记录写入输出文件。对于我们的文件合并和去重任务,Reduce函数将接收到每个不同行内容的键-值对,并将它们合并为一个输出记录。输出记录的键是行内容,值是固定的值。 下面是一个伪代码实现: ```python class MergeAndDeduplicationMapper extends Mapper<LongWritable, Text, Text, Text> { public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // 将每一行作为一个键,将固定的值作为值 String[] lines = value.toString().split("\n"); for (String line : lines) { context.write(new Text(line), new Text("1")); } } } class MergeAndDeduplicationReducer extends Reducer<Text, Text, Text, Text> { public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { // 将相同的键合并为一个输出记录 context.write(key, new Text("1")); } } // 配置作业并运行 job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TextOutputFormat.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); job.setMapperClass(MergeAndDeduplicationMapper.class); job.setReducerClass(MergeAndDeduplicationReducer.class); FileInputFormat.addInputPath(job, new Path(inputPath)); FileOutputFormat.setOutputPath(job, new Path(outputPath)); job.waitForCompletion(true); ``` 在上面的代码,我们使用TextInputFormat作为输入格式,并使用TextOutputFormat作为输出格式。我们还指定了Mapper和Reducer类,并设置了输入和输出键-值的类型。最后,我们将输入和输出路径添加到作业,并运行作业。 在运行MapReduce作业后,我们将得到一个合并并去重后的输出文件,其包含所有不同的行内容。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南洲.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值