【Hadoop学习笔记】(一)——MapReduce的原理及使用

一、MapReduce概述

MapReduce是大数据离线计算的一种处理范式。它的基本概念就是“分而治之”:将单个问题分解成多个独立的子任务,再将子任务的结果汇聚成最终结果。

在 MapReduce 中,它会先把样本分成一段段能够令单台计算机处理的规模,然后让多台计算机同时进行各段样本的整理和统计,每执行完一次统计就对映射统计结果进行规约处理,最终完成大规模的数据规约。

MapReduce 的含义分为两步:Map 和 Reduce (映射规约) 。上述过程第一阶段的整理工作就是"映射",把数据进行分类和整理,得到一个相比于源数据小很多的结果。第二阶段的工作往往由集群来完成,整理完数据之后,将这些数据进行总体的归纳,映射的结果将会进一步缩略成可获取的统计结果

1. 键值对处理模式

键值对是 MapReduce 操作的基础,MapReduce 的处理过程大致如下:
{K1,V1} ——> {K2,List<V2>} ——> {K3,V3}

  1. MapReduce 作业的 map 方法的输入是一系列键值对 K1,V1
  2. map 方法的输出是一系列键以及与之关联的值列表 K2,List<V2>。(每个mapper 仅仅输出一系列单个的键值对,通过 shuffle 方法组合成键与值列表)
  3. K2、V2 作为 Reduce 的输入,最终输出另一串键值对 K3、V3

二、MapReduce API

由于MapReduce现在逐渐被其他计算框架所取代,这里主要介绍 MapReduce 的思想和基本使用方式

1. Mapper

Hadoop 提供了 Mapper 基类,一般情况需要自定义 mapper类继承该基类并重写指定方法:

public class Mapper<K1, V1, K2, V2> {
  protected void map(KEYIN key, VALUEIN value, 
                     Context context) throws IOException, InterruptedException {
    context.write((K2) key, (V2) value);
  }
}

map方法以输入的键值对作为参数,Context提供Hadoop框架多种通信机制,其中之一是输出 map 或 reduce 方法的结果

mapper示例:

public class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
    
    @Override
    protected void map(Object key, Text value, Mapper<Object, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
        String[] words = value.toString().split(" ");
        
        for (String str: words){
            word.set(str);
            context.write(word, one);
        }
    }
}

在该示例中,该作业使用 TextInputFormat 作为输入数据的格式。默认情况下,这种格式的键指的是文件的行号,值指的是内容。
对于输入源中的每行文本,mapper 都会执行一次,每次运行会把该行内容切分成词语,并使用 Context 以 <word,1>格式输出新的键值对

2. Reducer

Reducer基类:

public class Reducer<K2, V2, K3, V3> {
  protected void reduce(K2 key, Iterable<V2> values, Context context
                        ) throws IOException, InterruptedException {
    for(V2 value: values) {
      context.write((K3) key, (V3) value);
    }
  }
}

reducer示例:

public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
        int total = 0;
        for (IntWritable value : values) {
            total++;
        }
        context.write(key, new IntWritable(total));
    }
}

MapReduce会将每个键对应的值收集起来(暂不描述该过程),并对每个键执行一次 reducer

3. Hadoop自带的 mapper 和 reducer

Hadoop提供了几种常见的 Mapper 和 Reducer 的实现:

  • InverseMapper:倒转键值对
  • TokenCounterMapper:对输入的每行文本的离散令牌进行计数
  • IntSumReducer:输出每个键对应整数值列表的总和
  • LongSumReducer:输出每个键对应长整数值列表的总和

这里的 TokenCounterMapper 和 IntSumReducer 可以取代上述的 WordCountMapper 和 WordCountReducer

4. combiner

由于 mapper 的输出量通常很大,为了减少数据的传输量提高性能,可以添加 combiner 对数据进行早期的聚合以减少传输的数据量。
combiner 同样实现自 Reduce类,要注意的是,Hadoop 不保证 combiner 被执行的次数!可能根本不执行或被执行多次。

使用 combiner 需要对上面的 reducer 进行修改:

@Override
    protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
        int total = 0;
        for (IntWritable value : values) {
            total += val.get();
        }
        context.write(key, new IntWritable(total));
    }

三、MapReduce原理

MapReduce的整体工作流程如下:

  1. 启动:驱动程序开启本地主机与 JobTracker 的通信。JobTracker 负责作业调度和执行,负责与 NameNode 通信,并对储存在 HDFS 上的数据相关的所有交互进行管理
  2. 输入分块:HDFS 文件通常被分成至少 64MB 的数据块,JobTracker 会将每个数据块分配给一个 map 任务
  3. 任务分配:JobTracker 确定所需的 map 任务数后,会去检查集群中的主机数,正在运行的 TaskTracker 数以及可并发执行的 map 任务数(用户自定义配置)。JobTracker 会查看各个输入数据块在集群中的分布位置,并尝试建立一个合理的执行计划,使 TaskTracker 尽可能处理位于相同物理主机上的数据块以提高性能

由于默认情况下,每个数据块会被复制到三台不同的主机,所以在本地处理大部分数据块任务计划的可能性比想象的高

  1. 任务启动:每个 TaskTracker 开启一个独立的 Java虚拟机来执行任务:
    • 如果集群有能力一次性执行所有任务,每个TaskTracker 会将分块复制到本地文件系统,启动所有任务
    • 否则 JobTracker 将维护起一个挂起任务队列,并在节点完成最初分配的 map 任务后,将挂起任务分配给各个节点。
  2. 监视 JobTracker :JobTracker 会不断与 TaskTracker 交换心跳和状态消息,跟踪进度和问题,并收集指标
  3. mapper 输入和执行:执行我们自定义的 mapper
  4. shuffle:在 map 和 reduce 之间,会有一个 shuffle 阶段,对数据进行整理
  5. 分块:Reduce 接口的隐形保证:给定键相关的所有值会被提交到同一个 reducer。因此需要将 mapper 的输出结果分块,使其分别传入相应的各个 reducer。分块文件保存在本地节点的文件系统
  6. reducer类的输入:reducer的 TaskTracker 从 JobTracker 接收更新,指明集群中哪些节点承载着输出分块。 TaskTracker 从各个节点获取分块,并合并为一个文件反馈给 reduce 任务
  7. reducer的执行和输出
  8. 关机

四、MapReduce其他功能

  • Hadoop Streaming:可以用任何使用标准输入和输出的脚本语言运行 map 和 reduce 任务。可以在对数据进行前期分析时使用 Streaming, 在实现运行于产品集群的作业时使用 Java 语言
  • ChainMapper:可以顺序执行多个 mapper,通过它执行多个 map 型任务再应用于 reducer。可以将复杂的 map 任务分解成一系列较小且更有针对性的 map 任务
  • Distributed Cache:Hadoop 提供的分布式缓存,可为所有任务提供共享的引用数据
  • 计数器:可以运用计数器、任务状态信息和 debug 日志进行高效的作业分析。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值