MapReduce及其工作机制 (Book Review & Personal Conclusion)

MapReduce

MapReduce作为一种分布式处理数据的编程模型,可以将big data 分析tasks交给任何一个拥有足够机器组成的集群环境的node上。为了能够并行地处理大规模的数据,我们需要将对数据的查询表示成MapReduce 作业。 

MapReduce主要分为两个阶段: map阶段reduce阶段。每个阶段都以key/value对作为输入和输出,类型格式由程序员根据编程需要设定。 在实际的编程当中,我们能够自行地对map函数和reduce函数进行定义。其中,

 map阶段

定义的map函数在编程应用中充当的职能常见的有:

① 数据准备阶段,通过这种方式来准备数据,使reduce函数能够在该数据上直接处理

② 筛选掉不符合条件的数据

Hadoop会将map阶段的输入数据划分成等长的小数据块,这个过程被称为input split。 Hadoop 会为每个分片构建一个map任务,并由该任务来运行用户自定义的map函数从而处理分片中的每个record。

【关于分片所引发的性能问题】

为了并行的处理大规模数据,使集群上的各个节点能够高效率的完成数据处理工作,得到最好的负载平衡质量,Split切分的大小尺度攸关重要。如果切分的太小,管理分片的时间,构建map热舞的时间将会决定作业的整体时间。因此一个合理的分片大小趋向于HDFS的一个块的大小,默认情况下是 64MB, 在实际的项目应用中,我们可以针对集群特点调整这个默认值(可以在新建所有文件或新建每个文件时指定)以适应我们的具体需求。

map函数处理的输出结果放在运行map任务的tasktracker的本地磁盘上,不会放到HDFS中。目的肯定是为了不浪费HDFS的资源。map函数开始产生输出时,并不是简单地将它写到磁盘。而是利用缓冲的方式写到内存,出于对效率的考虑进行预排序。

reduce阶段

经过map函数处理之后的输出将作为reduce函数的输入,单个reduce任务的输入通常来自所有mapper的输出。值得注意的是,这个处理过程需要根据key/value对进行分组和排序。

reduce输出写入到HDFS上是需要占用网络带宽的。

每个map任务的完成时间可能不同,因此只要有一个任务完成,reduce任务就会开始复制其输出——reduce任务的copy phase。reduce任务有少量复制线程,因此能够并行取得map输出。默认值是5个线程,可以通过设置mapred.reduce.parallel.copies属性来改变。

reduce任务的数量并非由输入数据的大小决定,而是特别指定的。如果有多个reduce任务,则每个map任务都会对其输出进行分区partition,为每个reduce任务建一个分区。分区由用户定义的分区函数控制,默认的partitioner通过哈希函数来分区,效率高。<关于任务数据流的shuffle:系统执行排序的过程,将map输出作为输入传给reducer,就成为shuffle。>

 特殊情况: 允许没有任何reduce任务。

运行MapReduce任务

map函数和reduce函数都定义好之后,我们需要运行MapReduce作业,JobClient类的静态函数runJob()会提交作业并等待任务的完成,最后将其进展情况写到控制台。

在运行MapReduce作业的过程中,一旦构造JobConf对象之后,我们需要指定输入数据和输出数据的路径。

① 输入路径: 调用FileInputFormat类的静态函数addInputPath()来定义输入数据的路径,该路径可以使目录,单个文件或是符合特定文件模式的一组文件。同时可以多次调用addInputPath()实现多路径输入。

② 输出路径: reduce函数的输出文件的写入目录由FileOutputFormat类中的静态函数setOutputPath()来指定 (p.s 在运行task前,该目录应该不存在,否则Hadoop会报错并refuse run该任务——为了防止数据覆盖、丢失)。

当MapReduce工作流中的job不止一个时,我们需要管理job的执行顺序,可以考虑是否有一个线性的job链或一个更复杂的job Direct Acyclic Graph,DAG有向无环图。对于前者,最简单的方法是one by one地运行作业,等前一个job运行结束后在运行下一个。

MapReduce工作机制

了解一种框架的工作机制是为应用该框架奠定基础。Hence, 如果想要编写高级的MapReduce程序,我们亟需做的就是了解MapReduce的工作机制。MapReduce的工作过程,包括如下四个独立的实体:

1. 客户端:提交MapReduce Job

2. jobtracker: 协调作业的运行。jobtracker是一个Java程序,JobTracker为主类。

3. tasktracker:运行job划分后的task。tasktracker是一个Java程序,TaskTracker为主类。

4. 分布式文件系统,用来在其他实体间共享job文件。

A) job的提交

1. 向jobtracker请求一个新的jobID

2. 检查job的输出说明

3. 计算job的input split

4. 将运行job所需要的资源复制到一个以jobID命名的目录下jobtracker的文件系统中

5. 通知jobtracker job准备执行。

B) job的初始化

JobTracker接收到对其job提交方法的调用之后,会把这个调用放入一个内部队列中,交由 job scheduler进行调度,并对其进行初始化。

C) 任务的分配

tasktracker运行一个简单的循环来定期发送heartbeat给jobtracker。 heartbeat通知jobtracker,tasktracker是否还存活,同时也作为两者之间的消息通道。

对于map任务和reduce任务,tasktracker有固定数量的任务槽。准备数量有tasktracker核的数量和内存大小来决定。

D) 任务的执行

继上一步之后,tasktracker已经被分配了一个任务,下一步是运行该任务。

1. 通过从共享文件系统把job的JAR文件复制到tasktracker所在的文件系统,从而实现job的jar文件本地化。同时,tasktracker将应用程序所需要的全部文件从分布是缓存复制到本地磁盘

2. tasktracker为任务新建一个本地工作目录,并把JAR文件中的内容解压到这个文件夹下

3. tasktracker新建一个TaskRunner实例运行任务。

E) Job的完成

当jobtracker收到job最后一个任务已完成的通知后,就会将job的状态设置为“successful”。最后,jobtracker清空job的工作状态,指示tasktracker清空job的工作状态(e.g 删除中间输出)。

Task失败

最常见的情况: map或reduce任务中用户代码抛出异常。

tasktracker失败

如果一个tasktracker由于崩溃或运行或运行缓慢而失败,它将停止向jobtracker发送heartbeat。jobtracker会注意到已经停止发送heartbeat的tasktracker,并将它从等待任务调度的tasktracker中移除。如果tasktracker上面的失败任务数高于集群的平均失败任务数,它就会被列入黑名单。被列入黑名单的tasktracker可以通过重启从jobtracker的黑名单中移除。

jobtracker失败

最严重的失败。发生的概率小。

job的调度

MapReduce的调度器是可选的。默认的调度器为原始的基于队列的FIFO(先进先出)调度器,此外还有Fair Scheduler和Capacity Schedule(针对多用户调度),这些都是通过设置mapred.jobtracker.taskScheduler属性来选择的。

附加

调试工具: Hadoop提供的辅助工具:IsolationRunner,这个工具允许在失败的相同输入数据上运行task。在MapReduce中,map和reduce函数的独立测试非常方便。为了方便验证输出的正确性,推荐使用目前开源的框架,例如Mockito。

任务剖析(task profiling):执行一些标准检查,借此加快MapReduce程序的运行,然后再做任务剖析。为了简化分析过程,可使用Hadoop提供钩子Hook作为辅助。

辅助类GenericOptionParser用来解释常用的Hadoop命令行选项,并根据需要,为configuration对象设置相应的取值。通常情况下,不会直接使用GenericOptionParser,更方便的实现是:实现Tool接口,通过ToolRunner来运行应用程序,ToolRunner内部调用GenericOptionsParser:

public interface Tool extends Configuration {
    int run (String args[]) throws Exception;
}
可以使用MapReduce的Web界面浏览job信息:跟踪job运行进度、查找job完成后的统计信息等。浏览地址:http://jobtracker-host:50030/

Job调优检查表:

范围最佳实践备注
mapper的数量先判断mapper需要运行多长时间?如果平均只需要几秒钟,则可以看是否能够用最少的mapper运行更长的时间,一般情况,一分钟左右。时间长度取决于使用的输入格式
reducer的数量为了达到最高性能,集群中reducer数量应该略少于reducer的任务熟。这将使得reducer能够在同一个周期完成任务,并在reducer阶段充分使用集群
combiner作业能否充分利用combiner以减少通过shuffle传输的数据量?
中间值的压缩对map输出进行压缩几乎总能够使job执行的更快
自定义序列化如果正在使用自定义的Writable对象或自定义的comparator,则必须确保已经实现RawComparator
调整shuffleMapReduce的shuffle过程可以对一些内存管理的参数进行调整,以弥补性能的不足。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值