zoukankan      html  css  js  c++  java
  • MapReduce 过程详解 (用WordCount作为例子)

    本文转自 http://www.cnblogs.com/npumenglei/

    ....

    先创建两个文本文件, 作为我们例子的输入:

                           

    File 1 内容:

    My name is Tony

    My company is pivotal

    File 2 内容:

    My name is Lisa

    My company is EMC

    1. 第一步, Map

    顾名思义, Map 就是拆解.

    首先我们的输入就是两个文件, 默认情况下就是两个split, 对应前面图中的split 0, split 1

    两个split 默认会分给两个Mapper来处理, WordCount例子相当地暴力, 这一步里面就是直接把文件内容分解为单词和 1 (注意, 不是具体数量, 就是数字1)其中的单词就是我们的主健,也称为Key, 后面的数字就是对应的值,也称为value.

    那么对应两个Mapper的输出就是:

    split 0

    My       1

    name    1

    is         1

    Tony     1

    My          1

    company     1

    is       1

    Pivotal   1

    split 1

    My       1

    name    1

    is       1

    Lisa     1

    My       1

    company  1

    is       1

    EMC     1

    2. Partition

    Partition 是什么? Partition 就是分区。

    为什么要分区? 因为有时候会有多个Reducer, Partition就是提前对输入进行处理, 根据将来的Reducer进行分区. 到时候Reducer处理的时候, 只需要处理分给自己的数据就可以了。 

    如何分区? 主要的分区方法就是按照Key 的不同,把数据分开,其中很重要的一点就是要保证Key的唯一性, 因为将来做Reduce的时候有可能是在不同的节点上做的, 如果一个Key同时存在于两个节点上, Reduce的结果就会出问题, 所以很常见的Partition方法就是哈希。

    结合我们的例子, 我们这里假设有两个Reducer, 前面两个split 做完Partition的结果就会如下:

    split 0

    Partition 1:
    company 1
    is      1
    is    1


    Partition 2:
    My     1
    My    1
    name  1
    Pivotal   1
    Tony    1

    split 1

    Partition 1:
    company 1
    is    1

    is      1
    EMC   1


    Partition 2:
    My     1
    My       1
    name   1
    Lisa     1

    其中Partition 1 将来是准备给Reducer 1 处理的, Partition 2 是给Reducer 2 的

    这里我们可以看到, Partition 只是把所有的条目按照Key 分了一下区, 没有其他任何处理, 每个区里面的Key 都不会出现在另外一个区里面。

    3. Sort

    Sort 就是排序喽, 其实这个过程在我来看并不是必须的, 完全可以交给客户自己的程序来处理。 那为什么还要排序呢? 可能是写MapReduce的大牛们想,“大部分reduce 程序应该都希望输入的是已经按Key排序好的数据, 如果是这样, 那我们就干脆顺手帮你做掉啦, 请叫我雷锋!”  ......好吧, 你是雷锋.

    那么我们假设对前面的数据再进行排序, 结果如下:

    split 0

    Partition 1:
    company 1
    is      1
    is    1


    Partition 2:
    My     1
    My    1
    name  1
    Pivotal   1
    Tony    1

     split 1

    Partition 1:
    company 1
    EMC   1
    is    1

    is      1

    Partition 2:
    Lisa   1
    My     1
    My       1
    name   1

     这里可以看到, 每个partition里面的条目都按照Key的顺序做了排序

    4. Combine

    什么是Combine呢? Combine 其实可以理解为一个mini Reduce 过程, 它发生在前面Map的输出结果之后, 目的就是在结果送到Reducer之前先对其进行一次计算, 以减少文件的大小, 方便后面的传输。 但这步也不是必须的。

    按照前面的输出, 执行Combine:

    split 0

    Partition 1:
    company 1
    is      2

    Partition 2:
    My     2
    name  1
    Pivotal   1
    Tony    1

     split 1

    Partition 1:
    company 1
    EMC   1
    is    2

    Partition 2:
    Lisa   1
    My     2
    name   1

     我们可以看到, 针对前面的输出结果, 我们已经局部地统计了is 和My的出现频率, 减少了输出文件的大小。

    5. Copy

    下面就要准备把输出结果传送给Reducer了。 这个阶段被称为Copy, 但事实上雷子认为叫他Download更为合适, 因为实现的时候, 是通过http的方式, 由Reducer节点向各个mapper节点下载属于自己分区的数据。

    那么根据前面的Partition, 下载完的结果如下:

    Reducer 节点 1 共包含两个文件:

    Partition 1:
    company 1
    is      2

    Partition 1:

    company  1

    EMC    1

    is    2

    Reducer 节点 2 也是两个文件:

     Partition 2:

    My     2
    name  1
    Pivotal   1
    Tony    1

    Partition 2:

    Lisa   1

    My     2

    name   1

    这里可以看到, 通过Copy, 相同Partition 的数据落到了同一个节点上。

    6. Merge

    如上一步所示, 此时Reducer得到的文件是从不同Mapper那里下载到的, 需要对他们进行合并为一个文件, 所以下面这一步就是Merge, 结果如下:

    Reducer 节点 1

    company 1
    company  1
    EMC    1

    is      2
    is    2

    Reducer 节点 2

    Lisa  1
    My     2
    My    2

    name  1
    name  1

    Pivotal   1

    Tony    1

    7. Reduce

    终于可以进行最后的Reduce 啦...这步相当简单喽, 根据每个文件中的内容最后做一次统计, 结果如下:

    Reducer 节点 1

    company 2
    EMC    1

    is      4

    Reducer 节点 2

    Lisa  1
    My     4

    name  2

    Pivotal   1

    Tony    1

    至此大功告成! 我们成功统计出两个文件里面每个单词的数目, 同时把它们存入到两个输出文件中, 这两个输出文件也就是传说中的 part-r-00000 和 part-r-00001, 看看两个文件的内容, 再回头想想最开始的Partition, 应该是清楚了其中的奥秘吧。

    如果你在你自己的环境中运行的WordCount只有part-r-00000一个文件的话, 那应该是因为你使用的是默认设置, 默认一个job只有一个reducer

    如果你想设两个, 你可以:

    1. 在源代码中加入  job.setNumReduceTasks(2), 设置这个job的Reducer为两个
    或者
    2. 在 mapred-site.xml 中设置下面参数并重启服务
    <property>
      <name>mapred.reduce.tasks</name>
      <value>2</value>
    </property>

    这样, 整个集群都会默认使用两个Reducer

    结束语:

    本文大致描述了一下MapReduce的整个过程以及每个阶段所作的事情, 并没有涉及具体的job,resource的管理和控制, 因为那个是第一代MapReduce框架和Yarn框架的主要区别。 而两代框架中上述MapReduce 的原理是差不多的,希望对大家有所帮助。 

  • 相关阅读:
    脏读 幻读 不可重复读
    按位与、或、异或等运算方法
    java适配器模式
    servlet/filter/listener/interceptor区别与联系
    Struts2、SpringMVC、Servlet(Jsp)性能对比 测试
    Struts2的优点与Struts1的区别:
    ITOO 第一个任务,新建界面
    导出word使用模版
    【Web前端】---js调用本地应用程序
    JQuery经典小例子——可编辑的表格
  • 原文地址:https://www.cnblogs.com/silva/p/4487315.html
Copyright © 2011-2022 走看看