zoukankan      html  css  js  c++  java
  • MapReduce论文笔记

    用户编写Map和Reduce函数,Map函数的调用是针对一对<k,v>的,即如果输入有5对<k,v>,那么Map函数就会调用5次。
    对于每一次:
         输入一对<k,v>,然后进行某些用户定义的操作,可以emit 出 一对或者多对的<k,v>

    这些Map函数输出的<k,v>写到本地的内存中,周期性的,这些内存中的数据对被写到本地磁盘上。

    Reduce函数的输入是< k,list<v> > ,即相同的key的value会被串在一个list里面。然后Reduce函数对于每条这样的输入进行某些用户自定义的
    操作,典型情况下,对于一次Reduce函数的调用,它会产生0个或者1个的<k,v>对。


    Reduce worker 的调用是在很多机器上并行的,Reduce的worker的数目R是由partitioning 函数(比如 hash(key) mod R)决定的,用户指定partition函数和R。
    执行流程:

    当用户程序调用MapReduce函数后,会执行以下的流程:

    1 用户程序的MapReduce库将输入文件切分成M个Split(一个Split的大小通常在16M和64M之间,GFS的block大小一般是64M),这个参数可以由用户设置,然后,用户程序会fork出许多的副本在集群的很多的机器上。

    2 在这些进程副本中,其中有一个副本进程比较特殊,叫做master进程。其他的都叫做worker进程,由master来分配任务。现在一共有M个Map任务和R个Reduce任务,master进程会选择空闲的worker进程,对它分配一个Map任务或者一个Reduce任务。

    3 被分配到Map任务的worker进程会读取自己相应部分的Split,然后worker对Split中的每对<key,value>调用一次Map函数,也就是说,如果有10对
    ,Map函数就调用10次,Map函数产生的输出buffer到本地内存中。

    4 周期性的,buffer到内存中的key/Value对会被写到本地磁盘,被partition函数切分成R份,每份一个文件。worker进程会将这R个文件的位置
    报告给master进程,master进程负责将这R个文件的位置报告给其它的Reduce worker。

    5  当一个reduce worker被master通知了这些文件的位置后,它就是用RPC去读取Map Workers上面的相应的文件。当一个reduce worker将所有它需要读取的文件都读取过来后,reduce worker进程会对所有的key/Value对进行排序(这个过程有必要,因为不同的key的pair会被map到同一个reduce worker),以便将同一个key的value给放在一个list中。这个过程中,如果数据量太大,可以使用外排。

    6 reduce worker遍历所有的Key/Value对,将unique的Key和其对应的所有的value,以<Key, list<value>>的形式传给Reduce函数,也就是说,如果有10个不同的Key,那么Reduce会被调用10次。每次Reduce函数调用的输出都会被append到这个reduce worker的一个最终的输出文件。(也就是说,一个reduce worker只会产生一个文件)

    7 当所有的Map任务和Reduce任务都完成时,Master进程唤醒用户程序,这时,用户程序的MapReduce函数调用返回给用户代码。

    最后,一共产生了R个输出文件,每个Reduce worker一个文件。这些文件会被保存到分布式文件系统上。


    Master维护的数据结构:

    Master进程需要维护每个Map,Reduce 任务的状态,有三种状态,idle,in-progress, completed,对于非idle状态的Map或者Reduce任务,它还需要维护执行这个任务的worker 机器的id。

    Master进程还需要保存每个Map任务产生的R个文件的位置信息和大小。这些信息被增量的push到in-progress状态的Reduce worker上去 

    容错

    worker failure:

    master进程会周期性的ping worker进程,如果某个worker进程在某一段时间内没有回应,那么master认为这个worker进程死了,就会把所有由死了的worker执行完成的Map任务或者in-progress状态的Map或者Reduce任务都重新标记为 idle状态,这样,这样idle的任务以后还需要被调度。

    当一个Map任务首先被worker A执行,A失败后,然后在worker B上重新执行的情况下,这个重新执行会被通知给Reduce worker。

    master failure:

    当前的实现是如果master失败,那么MapReduce任务失败,客户端可以察觉这个情况进行重试。可以定时的对master维护的数据结构进行checkpoint,这样下次一个新的master启动的时候,去读checkpoint恢复状态。

    Locality:

    输入数据是存储到GFS上面的,GFS将每个文件划分成64M的block,每个block保存3份副本,框架会将Map任务调度到有自己的输入数据的副本的机器上。

    任务粒度:

    通常M和R的大小会远远比worker machine的数量多。所以通常一个worker会做许多任务。

    关于M的选择:通常会使得每个Map任务处理的数据的大小在16M~64M大小之间(通常小于GFS的Block的大小),这样有利于locality的优化。
    关于R的选择:通常选择R为worker machine的小的倍数。

    Combiner 函数

    Combiner针对Map的输出,对Map的输出进行合并后,然后再传出去。
    比如某个Map任务会输出很多的key,Value对,如果直接把它们发出去,可能会占用大量的带宽,所以可以用Combiner函数先对这些pairs进行
    预处理,然后再shuffle。Combiner函数在执行Map任务的机器上运行。典型情况下,Combiner函数和Reduce函数差不多。

    输入

    MapReduce框架支持很多的输入模式,比如text mode,将文件的每行解析为一个key/value对,key为这行的起始字符在文件中的便宜,value就是这行的内容。还支持按key排序的key/value对的顺序存储。每种输入类型的实现都知道怎么对输入文件进行split,以使得不会破坏数据,比如text mode中,split的过程会保证split的边界在行的边界上。用户可以自定义新的输入类型。
  • 相关阅读:
    还在使用golang 的map 做Json编码么?
    Golang 性能测试(2) 性能分析
    golang 性能测试 (1) 基准性能测试
    消息队列 NSQ 源码学习笔记 (五)
    消息队列 NSQ 源码学习笔记 (四)
    消息队列 NSQ 源码学习笔记 (三)
    消息队列 NSQ 源码学习笔记 (二)
    消息队列 NSQ 源码学习笔记 (一)
    你不知道的空格
    Supervisor 使用和进阶4 (Event 的使用)
  • 原文地址:https://www.cnblogs.com/foxmailed/p/2301347.html
Copyright © 2011-2022 走看看