MapReduce的5个流程
- [input阶段]获取输入数据进行分片作为map的输入
- [map阶段]过程对某种输入格式的一条记录解析成一条或多条记录
- [shffle阶段]对中间数据的控制,作为reduce的输入
- [reduce阶段]对相同key的数据进行合并
- [output阶段]按照格式输出到指定目录
抽象类InputFormat
整个类结构:
InputFormat作为一个抽象类,定义了两个功能:
public abstract class InputFormat<K, V> {
public abstract List<InputSplit> getSplits(JobContext context) throws IOException, InterruptedException;
public abstract RecordReader<K,V> createRecordReader(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException;
}
- getSplits()功能:
对于输出文件做逻辑上的分片工作,getSplits()方法将文件切分成InputSplit,InputSplit的个数对应map()方法的个数。
- createRecordReader()功能:
对于切分的InputSplit提取每一条记录,解析为<k,v>对的形式供map()处理
抽象类FileInputFormat
- 抽象类FileInputFormat继承了InputFormat类,并实现了getSplits()方法.
你的分布式文件通过block形式存储,hadoop3默认为blockSize=128MB默认配置下,切分文件时,split大小和block大小是相同的,如上图文件默认被8个split,每个大小和block大小一致,最后一个split计算真实大小。
细节查看参考文章
到这里split的划分就介绍完了,但是有一个问题需要考虑:
- 如果一个record跨越了两个split该怎么办?
普通类TextInputFormat
-TextInputFormat类继承了FileInputFormat类,并实现了createRecordReader()方法
@Override
public RecordReader<LongWritable, Text>
createRecordReader(InputSplit split,
TaskAttemptContext context) {
String delimiter = context.getConfiguration().get(
"textinputformat.record.delimiter");
byte[] recordDelimiterBytes = null;
if (null != delimiter)
recordDelimiterBytes = delimiter.getBytes(Charsets.UTF_8);
return new LineRecordReader(recordDelimiterBytes);
}
这从配置中读取了文本的记录之间的分隔符,如果不另外在设置别的分隔符,这里的recordDelimiterBytes就是空值,默认分隔符为 \r或\n或\r\n。
因为优先考虑记录的完整性,当前位置小于即使在等于split的末尾,还会去读取下一个分片第一行的数据,当下一个split在读取的时候会初始化start position,跳过不完整记录。
分割的每一条记录,start position作为key,字节内容作为value。
解决了上面提出的问题–保证记录是完整的。
细节参考文章
普通类NLineInputFormat
- 此类继承了FileInputFormat类,并实现了createRecordReader()方法
public static final String LINES_PER_MAP =
"mapreduce.input.lineinputformat.linespermap";
public RecordReader<LongWritable, Text> createRecordReader(
InputSplit genericSplit, TaskAttemptContext context)
throws IOException {
context.setStatus(genericSplit.toString());
return new LineRecordReader();
}
功能是按照默认分割符切分,读入配置参数LINES_PER_MAP ,PER条记录合并为一条记录送到map()处理.
普通类KeyValueTextInputFormat
- 按照默认的分隔符分隔记录
- 对于每一条记录,按照 KEY_VALUE_SEPARATOR分割符 分割前面的是key,后面的是Value。
public static final String KEY_VALUE_SEPARATOR =
"mapreduce.input.keyvaluelinerecordreader.key.value.separator";
DBInputFormat
数据库读入
来源:CSDN
作者:qq_28027543
链接:https://blog.csdn.net/qq_28027543/article/details/103665946