目标
- InputFormat
- Partitioner
- Conbiner
- Sort
- OutputFormat
InputFormat
在数据进入map之前,会进过一系列的格式化操作
- 在客户端submitJob()方法提交作业前,会获取配置信息,形成一个任务分配的规划
- 提交文件分片(文件夹)和应用程序jar包
- MR运行MapTask根据InputFormat读取文件,这里将详细介绍InputFormat
InputFormat是一个抽象类,MR默认是用TextInputFormat方法读取文件
TextInputFormat是按行读取文件中的数据,实际上TextInputFormat中只实现了createRecordReader()和isSplitable()两个方法,它的具体实现在FileInputFormat中就已经实现的,FileInputFormat也是一个抽象类。
NLineInputFormat也继承于FileInputFormat,它的特点是按特定的行数读取数据
// 设置指定的InputFormat(重点) |
DBInputFormat继承于DBInputFormat的同时实现了InputFormat,这个方法可以从数据库中读取数据,写入HDFS,类似于Sqoop,需要注意的是它的实体类要同时继承DBWritable和Writable,提交到HDFS上执行的时候需要指定jdbc的jar包(不推介使用)。
Partitioner
MR的默认分区规则是按照key分区,相同的key到一个reduce方法中去,Partitoner可以自定义分区规则,自定义类继承Partitioner<Text, Flow>,泛型是map输出的key和value类型
参考代码
public class Partitoner extends Partitioner<Text, Flow> { |
要在Driver中指定Partitioner的类,并且指定reduce的个数,这里的reduce设置的个数一定要和Partitoner分区中返回的分区个数相同
// 设置Partitoner |
如果reduce设置的数量大于分区个数,则会产生空的输出文件,即空的reduce。
如果reduce设置的个数小于分区个数,则会报错,表示多余的数据没有分区可去。
java.io.IOException: Illegal partition for 13826544101 (2) |
Conbiner
Conbiner是合并,即是map阶段的reduce,可以自定义,也可以直接使用reduce方法,需要在Driver中指定,需要注意的是不能改变业务逻辑(不适用于乘积)
//设置conbiner |
Sort
Sort是分区排序,需要知道的是MR的key默认是有序的,如果要自定义排序规则需要将实体类实现WritableComparable<FlowSort>
接口,泛型就传入实体类的类名,WritableComparable实际上是继承了Writable和Comparable
实体类参考代码
|
需要注意的是使用自定义排序的实体类要放到mapreduce方法key的位置,使之有序。
主要注意的是Sort是每个reduce中有序,如果设置了多个reduce,则只能保证每个reduce内部有序
OutputFormat
有一类很常见的需求:按照一定的规则把数据给我写到某个文件中去
OutputFormat是一个接口,实现它的类有FileOutputFormat和DBOutputFormat,使用和InputFormat差不多,用的不多,不写了