分片
对于HDFS中存储的一个文件,要进行Map处理前,需要将它切分成多个块,才能分配给不同的MapTask去执行。分片的数量等于启动的MapTask的数量。默认情况下,分片的大小就是HDFS的blockSize。
分片是在读取文件之后就执行的
blockSize默认大小128M。
可通过设置minSize和maxSize来设置分片的大小。
PS:分片的大小直接影响到MapTask的数量,可根据实际的业务需求来调整分片的大小
分区
分区是在shuffle之前,本地聚合之后进行的
可以根据实际需求,把Map完的数据Reduce到不同的文件中。可通过setNumReduceTasks来设置分区的个数。
默认MapReduce使用HashPartitioner来进行分区。但有时,会造成数据倾斜,那么我们可以自定义分区算法。
代码实现
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Partitioner;
public class Partition extends Partitioner<Students, NullWritable> {
public int getPartition(Students students, NullWritable nullWritable, int numPartitions) {
if ("男".equals(students.getSex())) {
if (students.getClassName().startsWith("文")) {
return 0;
}
return 1;
} else {
if (students.getClassName().startsWith("理")) {
return 2;
}
return 3;
}
}
}
分区的下标是从0开始的
上面的是按照男文、男理、女文、女理分为四个区的
自定义了分区类还不够,还要再Driver设置Reduce Task的数量,要和分区数一样
job.setNumReduceTasks(4);
分组
分组再shuffle之后再Reduce之前执行的
分组是将某一个特定作为标准,以这个值进行分类,相同的类再同一组,放进一个reduce进行后续的处理
默认的是用Mapper 端输出的key来分组
代码实现
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
public class Group extends WritableComparator {
@Override
public int compare(WritableComparable a, WritableComparable b) {
Map_Trip trip1 = (Map_Trip)a;
Map_Trip trip2 = (Map_Trip)b;
return trip1.toString().compareTo(trip2.toString());
}
public Group(){
super(Map_Trip.class,true);
}
}
上述是按照key的toString来分组
同时要在Driver加上job.setGroupingComparatorClass(Group.class);