Hadoop MapReduce 深入理解!二次排序案例!

大数据之Hadoop学习——动手实战学习MapReduce编程实例 文章目录一、MapReduce编程实例1.自定义对象序列化需求分析报错:Exception in thread "main" java.lang.IllegalArgumentException: Wrong FS: hdfs://192.168.17.10:9000/workspace/flowStatistics/output, expected: file:///解答一、正常处理即可,不过在... 阅读详情

1. MapReduce 处理的数据类型

1.1 必须实现 org.apache.hadoop.io.Writable 接口。需要实现数据的序列化与反序列化,这样才能在多个节点之间传输数据!

示例:

public class IntWritable implements WritableComparable<IntWritable> , 
public interface WritableComparable<T> extends Writable, Comparable<T>

Writable 接口定义如下:

public interface Writable {
  void write(DataOutput out) throws IOException;
  void readFields(DataInput in) throws IOException;
}

在IntWritable中的实现如下:

  @Override
  public void readFields(DataInput in) throws IOException {
    value = in.readInt();
  }
  @Override
  public void write(DataOutput out) throws IOException {
    out.writeInt(value);
  }
1.2 Key 必须实现WritableComparable

在MapReduce的过程中,需要对key进行排序,而key也需要在网络流中传输,因此需要实现WritableComparable,这是一个标志接口,实现了Writable, Comparable两个接口。

在IntWritable中的实现如下:

 @Override
  public boolean equals(Object o) {
    if (!(o instanceof IntWritable))
      return false;
    IntWritable other = (IntWritable)o;
    return this.value == other.value;
  }

  @Override
  public int hashCode() {
    return value;
  }

  /** Compares two IntWritables. */
  @Override
  public int compareTo(IntWritable o) {
    int thisValue = this.value;
    int thatValue = o.value;
    return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
  }

2 InputFormat

接口声明如下:

public interface InputFormat<K, V> {

  InputSplit[] getSplits(JobConf job, int numSplits) throws IOException;

  RecordReader<K, V> getRecordReader(InputSplit split,
                                     JobConf job, 
                                     Reporter reporter) throws IOException;

InputFormat负责
1. 将输入文件进行逻辑切分(getSplits),每个分片形成一个InputSplit对象,每个InputSplit对象由一个Mapper对象(里面有我们自己需要实现的map方法)接收和处理,对应一个Map Task 任务。
2. 在一个Mapper对象处理一个InputSplit对象时,由getRecordReader方法提供更细致的切分,比如FileInputFormat是按行切分的,每行作为一个Mapper 的输入。

FileInputFormat的实现:
其中getSplits默认是按Block大小进行切分的。
getRecordReader仍然是个抽象函数。

默认情况下我们使用的是 public class TextInputFormat extends FileInputFormat

public RecordReader<LongWritable, Text> getRecordReader(
                                          InputSplit genericSplit, JobConf job,
                                          Reporter reporter)
    throws IOException {

    reporter.setStatus(genericSplit.toString());
    String delimiter = job.get("textinputformat.record.delimiter");
    byte[] recordDelimiterBytes = null;
    if (null != delimiter) {
      recordDelimiterBytes = delimiter.getBytes(Charsets.UTF_8);
    }
    return new LineRecordReader(job, (FileSplit) genericSplit,
        recordDelimiterBytes);
  }

可见,其先按行切分,然后按delimiter这个值切分得到一条条记录的。

3 Partitioner

3.1

经过InputFormat对数据的切分后,每个Mapper的输出结果是一系列的kv对,需要通过Patitioner把每条kv对标记为属于的某个Reducer,这样Reducer就可以拉取Mapper得到的结果。
接口定义如下:

public interface Partitioner<K2, V2> extends JobConfigurable {

  /** 
   * Get the paritition number for a given key (hence record) given the total 
   * number of partitions i.e. number of reduce-tasks for the job.
   *   
   * <p>Typically a hash function on a all or a subset of the key.</p>
   *
   * @param key the key to be paritioned.
   * @param value the entry value.
   * @param numPartitions the total number of partitions.
   * @return the partition number for the <code>key</code>.
   */
  int getPartition(K2 key, V2 value, int numPartitions);
}

默认情况下,我们使用的是HashPartitioner

public class HashPartitioner<K2, V2> implements Partitioner<K2, V2> {
   
   

  public void configure(JobConf job) {}

  /** Use {@link Object#hashCode()} to partition. */
  public int getPartition(K2 key, V2 value,
                          int numReduceTasks) {
    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  }

}

Partition过程
================================图3.1Partition过程================================

使用Hash的方式是所有的key的hashcode对reduce的数目取余数,因此虽然能够保证每个key相同的kv对会发送到同一个Reducer任务进行处理,但是当某个key对应的kv对数非常大,而其他却非常小时,这个Reducer节点就成了高负载节点,造成了计算资源的分配不均衡。

在Map阶段,可以使用job.setPartitionerClass设置的partition类进行自定义Partitioner
我们分析其过程:

job.java

  public void setPartitionerClass(Class<? extends Partitioner> cls
                                  ) throws IllegalStateException {
   
   
    ensureState(JobState.DEFINE);
    conf.setClass(PARTITIONER_CLASS_ATTR, cls, 
                  Partitioner.class);
  }

由以上设置过程中,可知,通过用户对job对象的属性设定,Partitioner的类入口被记录在了MRJobConfig.java的PARTITIONER_CLASS_ATTR中:这里PARTITIONER_CLASS_ATTR是一个key值,而 Partitioner.class是其对应的value值。

public static final String PARTITIONER_CLASS_ATTR = "mapreduce.job.partitioner.class";

当要找到这个Partitioner类时:
JobContextImpl.java

//public class JobContextImpl implements JobContext
  public Class<? extends Partitioner<?,?>> getPartitionerClass() 
     throws ClassNotFoundException {
    return (Class<? extends Partitioner<?,?>>) 
      conf.getClass(PARTITIONER_CLASS_ATTR, HashPartitioner.class);
  }

可见默认的是HashPartitioner。

而对于Hadoop2.0 newPAI在JobConf.java中有PartitionerClass的set和get方法。

  public void setPartitionerClass(Class<? extends Partitioner> theClass) {
   
   
    setClass("mapred.partitioner.class", theClass, Partitioner.class);
  }

而获取Partitioner的类入口为

//JobConf.java
  public Class<? extends Partitioner> getPartitionerClass() {
     
     
    return getClass("mapred.partitioner.class",
                    HashPartitioner.class, Partitioner.class);
  }

可见默认的partitioner 仍然是HashPartitioner。

3.2 但是真的是这样吗?

我们思考,当Reducer的数量只有1个的时候,上述的HashPartition而的逻辑岂不是白费了!?
我们在HashPartition类内部做如下修改:

public class HashPartitioner<K, V> extends Partitioner<K, V> {
   
   

  /** Use {
   
   @link Object#hashCode()} to partition. */
  public int getPartition(K key, V value,
                          int numReduceTasks) {
    int result = (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
    System.out.printf("hase-partition:key\t%s,val\t%s,result:%n",key.toString(),value.toString(),result);
    (new Exception()).printStackTrace();
    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  }

}

这样在调用HashPartitioner的过程中就会打印异常栈了。
然而当Reducer只有一个的时候,上述异常并没有被触发!
再次查看3.1节的分析,我们只是从job类入手观察了用户设置的Partitioner的调用方法和实现,然而并没有查看具体的MapTask类内部是如何获取partitioner的。
下面我们从main函数开始捋程序,想要尽快理解二次排序的朋友可以跳到第4节了。

3.3 真正的程序入口
3.3.1 在YARN上提交任务

WordCount.java类的main函数的最后一句话是这么写的:

MapReduce练习题 觉得有帮助的,请多多支持博主,点赞关注哦~ 文章目录MapReduce练习题一、单选题二、描述题三、MR排序练习案例1、统计手机用户信息1、统计每年、每月各个网站的总的上行流量和下行流量2、统计每年、每月各个网站的总的上行流量排名前两名的网站3、统计每年、每月各个网站的总流量排后两名的网站4、统计136,138手机用户,在2018年访问各个网站总流量排名前1的用户2、统计营业额信息1、计算出每个加... 阅读详情

相关推荐

LabVIew串口收发的一些问题

LabView串口收发实验总结

weixin_45508826的博客 2038

Mapreduce排序

1. Mapreduce排序 排序MapReduce的灵魂,MapReduce在Map和Reduce的两个阶段当中,都在反复地执行排序。 1.1 全局排序 排序分为全局排序、部分排序二次排序、辅助排序。全局排序,就是在一个MapReduce程序产生的输出文件中,所有的结果都是按照某个策略进行排序的,例如降序还是升序。MapReduce只能保证一个分区内的数据是key有序的,一个分区对应一个reduce,因此只有一个reduce就保证了数据全局有序,但是这样又不能用到Hadoop集群的优势。 1.

L13763338360的博客 4849

Win10或Win8下ObjectARX2015 Wizard向导创建项目失败解决方法

[原创]objectARX 2015 Wizard安装向导在Win8/win10下无法创建项目的解决方法总结 by edata @2017-5-1 objectARX 2015 Wizard安装向导在Win8/win10下无法创建项目的解决方法 因为Win8/Win10对系统盘(默认c:)使用了高级权限管理,所以在此盘下操作文件的修改工作都需要管理员权限才行。 基于这个原因,导致非管理员安

edata的博客 6994

MapReduce二次排序

MapReduce二次排序 二次排序的需求说明    在mapreduce操作时,shuffle阶段会多次根据key值排序。但是在shuffle分组后,相同key值的values序列的顺序是不确定的(如下图)。如果想要此时value值也是排序好的,这种需求就是二次排序。                                      ...

雪泪寒的博客 2318

mapreduce二次排序详解

mapreduce二次排序详解 - linzch3 - 博客园 什么是二次排序排序的数据具有多个字段,首先对第一个字段排序,再对第一字段相同的行按照第二字段排序,第二次排序不破坏第一次排序的结果,这个过程就称为二次排序。 如何在mapreduce中实现二次排序 mapreduce的工作原理 MR的工作原理如下图(如果看不清可右键新标签页查看): 图片部分数据参考自:HadoopMapReduce原理解析 相关重点: 分区(partitioning):使得具有相同Key值的键值.

hellojoy的博客 2737

Hadoop 二次排序

对value进行排序。 实现过程: 1.ComboKey(WritableComparable) 对比方法。 package com.mao.hdfs.secondSort; import org.apache.hadoop.io.WritableComparable; import java.io.DataInput; import java.io.Dat...

mthinking 270

Hadoop实现数据的二次排序

需求:对业务数据根据上行流量和上行总流量做一个排序处理,上行流量升序,上行流量相同的上行总流量升序 数据说明:7,8,9,10位置的数据类型分别为upFlow,dowFlow,upCountFlow,downCountFlow 1363157985066 13726230503 00-FD-07-A4-72-B8:CMCC 120.196.100.82 i02.c.aliimg.com 游戏娱乐 24 27 2481 24681 200 1363157995052 13826544101 5C-0E-8

yq7814326的博客 419

Hadoop二次排序MapReduce处理流程实例详解

一、概述 MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求,但是也是十分有限的,在我们实际的需求当中,往往有要对reduce输出结果进行二次排序的需求。对于二次排序的实现,网络上已经有很多人分享过了,但是对二次排序的实现原理及整个MapReduce框架的处理流程的分析还是有非常大的出入,而且部分分析是没有经过验证的。本文将通过一个实际的MapRe

DavidChen的博客 2629

Hadoop核心之MapReduce案例总结

MapReduce程序案例

weixin_44606952的博客 1780

深入理解hadoop排序

  MapReduce排序是默认按照Key排序的,也就是说输出的时候,key会按照大小或字典顺序来输出,比如一个简单的wordcount,出现的结果也会是左侧的字母按照字典顺序排列。下面我们主要聊聊面试中比较常见的全排序二次排序 一、全排序   全排序的方法一般有以下几种:     1.使用一个分区。但是该方法在处理大型文件的时候效率极低,因为一台机器必须处理所有的输出文...

aikunjiao3421的博客 220

从自定义排序深入理解单机hadoop执行mapreduce过程

我们对数据进行处理的过程中,最常见的一种操作是排序和统计,特别是在数据量大的场景,实现高效的排序是业务系统开发过程中非常重要的一块。本人所在的公司是个电商企业,交易量非常大,同时产生的财务数据量也是非常大,所以我们有多达几十T的数据都会存放到hadoop,如何从hadoop中高效地提取有用的数据成为了工作中重要的一环。在自定义排序类的过程中,遇到了不少问题,而hadoop执行过程中对异常的处理往往

lm2009200的博客 829

七、大数据技术之HadoopMapReduce

一、MapReduce概述 1.1 MapReduce定义 MapReduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并行运行在一个Hadoop集群上。 1.2 MapReduce优缺点 1.2.1 优点 1)MapReduce 易于编程 它简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的PC机器上运行。也就是说你写一个分布式程序

qq_38132995的博客 4333

hadoopMapReduce学习教程

hadoop之YARN学习 MapReduce概述 MapReduce定义 MapReduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并行运行在一个Hadoop集群上。 MapReduce优缺点 优点 易于编程 良好的扩展性 当你的计算资源不能得到满足的时候,你可以通过简单的增加机器来扩展它的计算能力。 高容错性 MapReduce设计的初

weixin_44178366的博客 697

MapReduce排序,分区,分组总结

1. 分区 1.1 自定义分区器 1) 自定义分区器继承 Partitioner类,并重写getPartition方法 2) 在driver类中设置使用 job.setPartitionerClass(PhoneNumPartitioner.class); 3) 设置reduce的个数 正常情况下,根据分区器业务来决定设置多少个,说白了就是分区器的逻辑会生成多少个分区, 则设置的多少个reduce 1.2 分区使用的注意事项: 1). reduce个数的设置 如果不设置,red

qq_43206800的博客 2100

Hadoop 3.1.3 (MapReduce

文章目录HadoopMapReduceMapReduce概述MapReduce优缺点MapReduce核心思想MapReduce进程官方WordCount源码常用数据序列化类型MapReduce编程规范WordCount案例实操本地测试集群上测试在Mac上向集群提交任务Hadoop序列化序列化概述自定义bean对象实现序列化接口(Writable)序列化案例实操需求编写MapReduce程序M...

VanasWang的博客 1895

什么是MapReduceMapReduce整体架构搭建使用介绍

本文是MapReduced的详细介绍,MapReducehadoop体系下的一种计算模型(计算框架|编程框架),主要是用来对存储在hdfs上的数据进行统计,分析的,分布式计算框架,用来解决分布式大数据平台下数据如何计算,资源调度,任务监控 主要用来整合hadoop集群中的资源(CPU 内存),进行统一调度 同时监控任务的执行情况,联合多个服务器节点的硬件,共同完成一个计算。突破单机服务器的计算能力,还介绍了Yarn分布式集群搭建使用MapReduce工作的原理源码分析............

虽千万人,吾往矣 2982

HadoopMapReduce详解

目录 一、 MapReduce概述 1.1 MapReduce定义 1.2 MapReduce优缺点 1.2.1 优点 1.2.2 缺点 1.3 MapReduce核心思想 1.4 MapReduce进程 1.5 官方WordCount源码 1.6 常用数据序列化类型 二、 Hadoop序列化 2.1 序列化概述 2.2 自定义bean对象实现序列化接口(Writable) 三、 MapReduce框架原理 3.1 InputFormat数据输入 3.1.1 切片与MapTas

Markble 4960

Hadoop-快速理解MapReduce原理】

MapReduce是一个分布式运算程序的编程框架,MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。(1)分布式的运算程序往往需要分成至少2个阶段。(2)第一个阶段的MapTask并发实例,完全并行运行,互不相干。(3)第二个阶段的ReduceTask并发实例互不相干,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出。

zhangqw1013的博客 954

深入理解 Apache Hadoop MapReduce

作者:禅与计算机程序设计艺术 1.简介 Apache Hadoop MapReduce是一个开源的分布式计算框架,用于处理海量的数据集并在不限定集群大小或机器配置的情况下运行作业。其主要由两类组件构成:Map 阶段和 Reduce 阶段。 Map阶段负责对数据进行分片并将每个分片传递给不同的任务,它接收

AI天才研究院 860

HadoopMapReduce框架原理

MapReduce框架原理:MapTask、Shuffle、ReduceTask工作机制的详细讲解

学习记录和总结 1万+

Android手机的Tasker使用指南

Android手机的Tasker使用指南,包括Tasker的各种操作的详细指导

上一篇: Hadoop-Streaming 高级参数
下一篇: JAVA基础重点难点笔记
Mr_Hagrid
博客等级 码龄16年 74粉丝 78原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值