MapReduce中的 分区,分组,排序(区别)

本文详细解析了MapReduce中的Partition分区、Group分组及Compare排序功能,包括其实现步骤、注意事项及对Reduce任务的影响。了解如何通过自定义规则提升数据处理效率。

2020-7-26

一. Partition分区:

功能:

按照条件将结果输入到不同的文件中

实现步骤:

自定义排序规则继承Partitioner类,重写getPartition()方法

在job驱动Driver中设置自定义排序规则

在Driver中根据分区数,设置ReduceTask数

分区数和ReduceTask关系

如果ReduceTask的数量(分区数)大于getPartition设置的数量,会产生空的输出文件

如果ReduceTask的数量大于1,getPartition又大于ReduceTask的数量,就会出现无处安放的数据,会抛出异常

如果ReduceTask的数量等于1,不管你设置了多少个分区,最后输出都会输出到一个文件里part-r-00000000

分区号必须是从0开始。例如:设置4个分区,则输出文件为编号为0,1,2,3。getPartition里面的分区指定也要符合这个规则

二. Group分组:

功能

发生在Reduce之前,增加reduce的并行度

实现步骤:

写一个分组类,继承WritableComparator类

重写构造方法

重写compare(WritableComparable a,
WritableComparable b)方法

Driver指定分组器setGroupingComparatorClass

意义:

合理使用,按照特定规则进行归纳,增加reduce
任务并行度,防止Reduce端数据倾斜

三. Compare排序:

功能:

MapReduce的排序主要是指的将Map输出的key进行排序

但是整个Shuffle中会用到四次排序,都会按照指定的排序规则排序

实现步骤

MapReduce提供的数据类型均已实现WritableComparable接口。

直接在对象中实现WritableComparable接口,重写write(),readFields(),compareTo(),三个方法。在compareTo方法里定义排序规则。

写一个排序比较器,继承WritableComparable,重写构造方法和compare方法。

在Driver中设置排序比较器器。
setSortComparatorClass(class);

注意

MapTask和ReduceTask均会对数据按照Key进行排序,该操作属于MR默认行为。

任何应用程序中的数据均会被排序,不论是否需要。MapTask输出的key必须实现writablecomparable接口,实现compareTo方法。即使指定排序规则,若key对象没有comperTo方法仍会抛出异常(指定的规则最终仍会调用key的compareTo)。所以MapTask输出的key无论如何必须实现WC接口

### 头歌平台中 MapReduce 实现分组排序的方法 在头歌平台上实现 MapReduce分组排序功能,通常遵循 Hadoop 中的标准流程。以下是关于如何通过自定义 Java Bean Comparator 来实现分组排序的具体说明。 #### 自定义 Java Bean 为了便于数据操作并支持排序序列化,需要创建一个实现了 `WritableComparable` 接口的类。此类需重写三个核心方法:`write`、`readFields` `compareTo` 方法[^3]。 - **write** 方法用于将对象序列化为字节流。 - **readFields** 方法负责反序列化过程。 - **compareTo** 方法则定义了键值之间的比较逻辑,决定了排序顺序。 ```java import org.apache.hadoop.io.WritableComparable; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; public class CustomBean implements WritableComparable<CustomBean> { private String state; // 州名 private int confirmedCases; // 确诊病例数 public CustomBean() {} public CustomBean(String state, int confirmedCases) { this.state = state; this.confirmedCases = confirmedCases; } @Override public void write(DataOutput out) throws IOException { out.writeUTF(state); out.writeInt(confirmedCases); } @Override public void readFields(DataInput in) throws IOException { this.state = in.readUTF(); this.confirmedCases = in.readInt(); } @Override public int compareTo(CustomBean other) { int cmpState = this.state.compareTo(other.state); // 首先按州名排序 if (cmpState != 0) return cmpState; return Integer.compare(this.confirmedCases, other.confirmedCases); // 再按确诊病例数排序 } @Override public String toString() { return state + "\t" + confirmedCases; } } ``` #### 定义 Partitioner 如果希望不同州的数据被分配到不同的 Reduce Task 上,则可以通过自定义 `Partitioner` 类来控制分区行为。默认情况下,Hadoop 使用哈希函数对 Key 值进行分区计算。然而,对于复杂场景下的精确分区需求,建议显式设置分区规则。 ```java import org.apache.hadoop.mapreduce.Partitioner; public class StatePartitioner extends Partitioner<CustomBean, NullWritable> { @Override public int getPartition(CustomBean key, NullWritable value, int numPartitions) { return Math.abs(key.getState().hashCode()) % numPartitions; } } ``` #### 设置 GroupingComparator 为了让相同州的数据进入同一个 Reduce 函数处理,还需要配置 `GroupingComparator`。此组件允许开发者基于特定字段重新定义分组依据。例如,在本例中可仅考虑州名称作为唯一标识符来进行分组。 ```java import org.apache.hadoop.io.RawComparator; public class StateGroupingComparator implements RawComparator<CustomBean> { @Override public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { try { DataInputStream dis1 = new DataInputStream(new ByteArrayInputStream(b1, s1, l1)); DataInputStream dis2 = new DataInputStream(new ByteArrayInputStream(b2, s2, l2)); String state1 = dis1.readUTF(); // 提取第一个记录中的州名部分 String state2 = dis2.readUTF(); // 提取第二个记录中的州名部分 return state1.compareTo(state2); } catch (IOException e) { throw new RuntimeException(e); } } @Override public int compare(CustomBean o1, CustomBean o2) { return o1.getState().compareTo(o2.getState()); } } ``` 最后一步是在 Job 初始化过程中注册这些组件: ```java job.setMapperClass(MapClass.class); job.setReducerClass(ReduceClass.class); // 指定输入/输出类型以及中间状态传输形式 job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); // 设定自定义bean结构体及其关联属性 job.setMapOutputKeyClass(CustomBean.class); job.setSortComparatorClass(StateGroupingComparator.class); job.setGroupingComparatorClass(StateGroupingComparator.class); job.setPartitionerClass(StatePartitioner.class); ``` 以上即为完整的 MapReduce 分组排序解决方案框架描述[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值