一、MapReduce解决了什么问题?
    · 在处理大规模问题时,每次都需要考虑多级并行协调、网络通信、处理错误、提高执行效率的问题
    
    · 这些问题严重降低了开发的效率,MapReduce编程模型就是用于解决这个问题的
    
    · 将这些通用性的问题抽象化,使得能让多台普通的机器也能处理大规模问题
    
    · MapReduce就是为了解决多级并行协调、网络通信、处理错误、提高执行效率等通用性问题的编程框架


二、MapReduce是什么?
    · 大量重复的编写数据处理类的程序中,所有数据处理的程序都有类似的过程:
        将一组输入的数据通过 map 函数返回成一个k-v键值对作为数据集;
        将具有相同key的数据输入到 reduce 函数中,最终返回处理后的结果。
    
    · 这一计算模型的优势就是并行化,map的过程可以在多台机器上并行处理,机器之间并不需要协调;
      所有的依赖性和协调过程都被用餐在map与reduce函数的数据分发之间;
      所以map和reduce都是可以并行执行的,但是reduce执行前必须要所有map函数执行完毕。(同步)

    · 在实际实现中,还必须要考虑可靠性和性能。
      大规模的机器产生局部性失败的几率时是很大的,因此必须要考虑在map过程中一个map任务失败的情况;
      如果因为一个map任务的失败导致整个过程都要重新计算,这样显然是不可接受的;
      因此分布式的容错性本质上就是如何在不可靠的硬件上构建可靠的软件。
    
    · 作为一个可靠的mapderuce方案就是一个利用普通机器组成的大规模计算集群进行并行的、高容错、高性能的数据处理函数框架。


三、MapReduce是如何实现的   (main节点+ map节点 +reduce节点)
    1. 用户需要实现指定 Map函数、Reduce函数、map任务的数量m、reduce任务r;
    2. 按照map数量m对总任务进行分割;
    3. 给map任务添加map函数;
    4. Map节点读取所划分的数据,解析成k-v格式,将k-v对传递给map函数,得到中间数据,将中间数据hash分桶平均放入r个临时文件;
    5. reduce节点pull拉取、读取对应的磁盘文件,按照key排序,这样相同的key就被排在了一起,因为是哈希分桶,所以相同的key一定在一个桶里;
    6. reduce节点遍历中间数据,将相同key的一组value传递给reduce函数追加输出到程序出口;

    主节点:
        1. 主节点用于调度每个节点的信息和工作情况(监控)
        2. 记录每个节点负责的数据部分   (故障重做)
        3. 通知deduce节点工作       (调度)
    

四、可能会出现的问题、改进思路
    · 工作节点的容错:
        多任务中,某个时间点的失败是常态的,所以必须要拥有容错度;
        1. map任务失败:
            主节点在分配map任务时记录分配情况;
            主节点通过心跳机制周期的检查map任务的执行情况;
            当有一个map任务出现故障,将这个map任务的数据分配给其他map任务执行

        2. reduce任务失败:
            因为reduce任务产生的结果有关于程序输出,
            为了中断的reduce任务产生的输出影响最终输出;
            让任务输出覆盖之前的输出。

        3. 主节点失败
            重试所有任务,或者设置检查点


    · 加速并行处理的过程
        1. 利用局限性
            在分布式系统中,算力很难成为系统瓶颈,网络带宽才是稀缺资源;
            在MapReduce中,至少需要M*R次网络传输才能将中间文件发送给reduce的节点;
            同时给map节点发送数据也是非常消耗网络带宽的;
            首先可以仅让本地机有数据的map节点做map任务;
            还可以采用流式传输的模式,当一个map任务执行完,立即调度reduce任务pull拉取数据到本地保存下来;

        2. 任务的粒度
            经验性的配置:map任务的数量为输入文件总大小除以64M的值
                         reduce的数量为map数量的一半
                         一个机器同时指定多个map reduce任务,通常为100%;
        3. 抢占机制、备用任务
            当一个节点的任务执行完,分担其他节点的一部分任务;
            当任务只剩1%时,所有节点都执行这一个任务的副本,当其中一个节点执行完,释放其他节点上的资源。


五、一些有价值的技巧
    · 划分函数
        按map函数输出的key决定当前k-v被划分到那一份中间数据
    · 顺序保证
        有事我们需要支持对数据文件按key进行随机访问或者顺序输出,并且为了减少reduce任务的负担;
        输出的每个map任务的中间数据的key都是有序的
    · 合并函数
        在map节点传向reduce节点之前,先做一次marge操作,减少网络负载
    · 输入和输出类型
        格式化输入输出接口
    · 确定性问题
        在思考问题前,先对环境做假设,如何在尽量实现假设,可以尽量实现解耦
    · 异常捕获、处理
        为了防止一个错误的数据导致任务不同重做,加入异常数据标记也是可行的
    · 本地执行
        先在本地简单的环境debug再考虑复杂情况
    · 状态信息
        分布式系统的客观性尤为重要,通过心跳机制可以尽量减少宕机造成的影响
    · 计数器/检查点
        为了防止调度器故障导致程序重做代价过大,在运行过程中设置检查点可以减少主节点宕机的代价