InputFormat&Partitioner&Conbiner&Sort&OutputFormat

目标

  1. InputFormat
  2. Partitioner
  3. Conbiner
  4. Sort
  5. OutputFormat

InputFormat

在数据进入map之前,会进过一系列的格式化操作

  1. 在客户端submitJob()方法提交作业前,会获取配置信息,形成一个任务分配的规划
  2. 提交文件分片(文件夹)和应用程序jar包
  3. MR运行MapTask根据InputFormat读取文件,这里将详细介绍InputFormat

InputFormat是一个抽象类,MR默认是用TextInputFormat方法读取文件

TextInputFormat是按行读取文件中的数据,实际上TextInputFormat中只实现了createRecordReader()和isSplitable()两个方法,它的具体实现在FileInputFormat中就已经实现的,FileInputFormat也是一个抽象类。

NLineInputFormat也继承于FileInputFormat,它的特点是按特定的行数读取数据

// 设置指定的InputFormat(重点)
NLineInputFormat.setNumLinesPerSplit(job, 3);
job.setInputFormatClass(NLineInputFormat.class);

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> {
@Override
public int getPartition(Text text, Flow flow, int i) {
String phone = text.toString();
if ("137".equals(phone.substring(0,3))){
return 0;
}else if ("136".equals(phone.substring(0,3))){
return 1;
}else{
return 2;
}
}
}

要在Driver中指定Partitioner的类,并且指定reduce的个数,这里的reduce设置的个数一定要和Partitoner分区中返回的分区个数相同

// 设置Partitoner
job.setNumReduceTasks(3);
job.setPartitionerClass(Partitoner.class);

如果reduce设置的数量大于分区个数,则会产生空的输出文件,即空的reduce。

如果reduce设置的个数小于分区个数,则会报错,表示多余的数据没有分区可去。

java.io.IOException: Illegal partition for 13826544101 (2)

Conbiner

Conbiner是合并,即是map阶段的reduce,可以自定义,也可以直接使用reduce方法,需要在Driver中指定,需要注意的是不能改变业务逻辑(不适用于乘积)

//设置conbiner
job.setCombinerClass(FlowReducer.class);

Sort

Sort是分区排序,需要知道的是MR的key默认是有序的,如果要自定义排序规则需要将实体类实现WritableComparable<FlowSort>接口,泛型就传入实体类的类名,WritableComparable实际上是继承了Writable和Comparable,Writable是Hadoop自己实现的,Comparable是Java中的类

实体类参考代码

@Override
public int compareTo(FlowSort o) {
return Long.compare(o.sum, this.sum);
}

需要注意的是使用自定义排序的实体类要放到mapreduce方法key的位置,使之有序。

主要注意的是Sort是每个reduce中有序,如果设置了多个reduce,则只能保证每个reduce内部有序

OutputFormat

有一类很常见的需求:按照一定的规则把数据给我写到某个文件中去

OutputFormat是一个接口,实现它的类有FileOutputFormat和DBOutputFormat,使用和InputFormat差不多,用的不多,不写了

Author: Tunan
Link: http://yerias.github.io/2018/10/13/hadoop/10/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.