99-104-Hadoop-MapReduce-排序:

99-Hadoop-MapReduce-排序:

WritableComparable 排序

排序是MapReduce框架中最重要的操作之一。 MapTask和ReduceTask均会对数据按 照key进行排序。该操作属于

Hadoop的默认行为。任何应用程序中的数据均会被排序,而不管逻辑上是否需要。 默认排序是按照字典顺序排序,且实现该排序的方法是快速排序。对于MapTask,它会将处理的结果暂时放到环形缓冲区中,当环形缓冲区使 用率达到一定阈值后,再对缓冲区中的数据进行一次快速排序,并将这些有序数 据溢写到磁盘上,而当数据处理完毕后,它会对磁盘上所有文件进行归并排序。 对于ReduceTask,它从每个MapTask上远程拷贝相应的数据文件,如果文件大小超过一定阈值,则溢写磁盘上,否则存储在内存中。如果磁盘上文件数目达到

一定阈值,则进行一次归并排序以生成一个更大文件;如果内存中文件大小或者 数目超过一定阈值,则进行一次合并后将数据溢写到磁盘上。当所有数据拷贝完 毕后,ReduceTask统一对内存和磁盘上的所有数据进行一次归并排序。

(1)部分排序

MapReduce根据输入记录的键对数据集排序。保证输出的每个文件内部有序。

(2)全排序

最终输出结果只有一个文件,且文件内部有序。实现方式是只设置一个ReduceTask。但该方法在处理大型文件时效率极低,因为一台机器处理所有文件,完全丧失了MapReduce所提供的并行架构。

(3)辅助排序:(GroupingComparator分组)

在Reduce端对key进行分组。应用于:在接收的key为bean对象时,想让一个或几个字段相同(全部字段比较不相同)的key进入到同一个reduce方法时,可以采用分组排序。

(4)二次排序

在自定义排序过程中,如果compareTo中的判断条件为两个即为二次排序。

WritableComparable 排序案例实操(全排序)(尚硅谷案例测试)

1)需求

根据案例 2.3 序列化案例产生的结果再次对总流量进行倒序排序。

(1)输入数据

原始数据 第一次处理后的数据

phone_data .txt part-r-00000(输入数据)

(2)期望输出数据

13509468723 7335 110349 117684

13736230513 2481 24681 27162

13956435636 132 1512 1644

13846544121 264 0 264

。。。 。。。

2)需求分析

99-104-Hadoop-MapReduce-排序:_第1张图片

代码地址:https://gitee.com/HaoZhouRS/bigdata-study-code/tree/master/big-data-study/MapReduce-Demom/src/main/java/com/zh/mapreduce/writableCompare

WritableComparable 排序案例实操(区内排序)

1)需求

要求每个省份手机号输出的文件中按照总流量内部排序。

2)需求分析

基于前一个需求,增加自定义分区类,分区按照省份手机号设置。

99-104-Hadoop-MapReduce-排序:_第2张图片

3)案例实操

(1)增加自定义分区类

package com.zh.mapreduce.partitionandwritableComparable;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
public class ProvincePartitionerTwo extends Partitioner {
    @Override
    public int getPartition(FlowBean flowBean, Text text, int numPartitions) {
        //获取手机号前三位
        String phone = text.toString();
        String prePhone = phone.substring(0, 3);
        //定义一个分区号变量 partition,根据 prePhone 设置分区号
        int partition;
        switch (prePhone) {
            case "136":
                partition = 0;
                break;
            case "137":
                partition = 1;
                break;
            case "138":
                partition = 2;
                break;
            case "139":
                partition = 3;
                break;
            default:
                partition = 4;
                break;
        }
        //最后返回分区号 partition
        return partition;
    }
}

(2)在驱动类中添加分区类

        job.setPartitionerClass(ProvincePartitionerTwo.class);
        job.setNumReduceTasks(5);

99-104-Hadoop-MapReduce-排序:_第3张图片

103-Hadoop-MapReduce-Combiner合并

Combiner 合并

(1)Combiner是MR程序中Mapper和Reducer之外的一种组件。

(2)Combiner组件的父类就是Reducer。

(3)Combiner和Reducer的区别在于运行的位置

​ Combiner是在每一个MapTask所在的节点运行;

​ Reducer是接收全局所有Mapper的输出结果;

(4)Combiner的意义就是对每一个MapTask的输出进行局部汇总,以减小网络传输量。

(5)Combiner能够应用的前提是不能影响最终的业务逻辑,而且,Combiner的输出kv 应该跟Reducer的输入kv类型要对应起来。 (场景,不能对结果有影响)

Mapper Reducer

3 5 7 ->(3+5+7)/3=5 (3+5+7+2+6)/5=23/5 不等于 (5+4)/2=9/2

2 6 ->(2+6)/2=4

(6)自定义 Combiner 实现步骤

​ (a)自定义一个 Combiner 继承 Reducer,重写 Reduce 方法

public class WordCountCombiner extends Reducer {
 private IntWritable outV = new IntWritable();
 @Override
 protected void reduce(Text key, Iterable values, Context 
context) throws IOException, InterruptedException {
 int sum = 0;
 for (IntWritable value : values) {
 sum += value.get();
 }
 
 outV.set(sum);
 
 context.write(key,outV);
 } }

(b)在 Job 驱动类中设置:

job.setCombinerClass(WordCountCombiner.class); 

Combiner 合并案例实操 (尚硅谷案例)

1)需求

统计过程中对每一个 MapTask 的输出进行局部汇总,以减小网络传输量即采用 Combiner 功能。

(1)数据输入

(2)期望输出数据

期望:Combine 输入数据多,输出时经过合并,输出数据降低。

2)需求分析

99-104-Hadoop-MapReduce-排序:_第4张图片

3)案例实操——方案一

(1)增加一个 WordCountCombiner 类继承 Reducer

package com.zh.mapreduce.combinerone;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class WordCountCombiner extends Reducer {
    private IntWritable outV = new IntWritable();
    @Override
    protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {
        int sum = 0;
        for (IntWritable value : values) {
            sum += value.get();
        }
        outV.set(sum);
        context.write(key,outV);
    }
}

(2)在 WordcountDriver 驱动类中指定 Combiner

// 指定需要使用 combiner,以及用哪个类作为 combiner 的逻辑
job.setCombinerClass(WordCountCombiner.class);

运行日志,输入122,输出5

99-104-Hadoop-MapReduce-排序:_第5张图片

job.setNumReduceTasks(0);//shuff机制在map、和reducer中间,混洗数据部分,没有reduce,直接会从map返回

4)案例实操——方案二

(1)将 WordcountReducer 作为 Combiner 在 WordcountDriver 驱动类中指定

// 指定需要使用 Combiner,以及用哪个类作为 Combiner 的逻辑 ,使用自己的reduce
job.setCombinerClass(WordCountReducer.class);

学习路径:https://space.bilibili.com/302417610/,如有侵权,请联系q进行删除:3623472230

你可能感兴趣的:(java,大数据,hadoop,hadoop,mapreduce,大数据)