Hadoop OutputCommitter
1. OutputCommitters
MapReduce使用一个提交协议来确保作业(job)和任务(task)都完全成功或失败。这个通过 OutputCommiter来实现。
新版本 MapReduce API中,OutputCommitter 由OutputFormat 通过getOutputCommitter() 方法确定。默认为FileOutputCommitter,适用于有文件输出的MapReduce任务。若是需要,也可以实现一个新的OutputCommitter类,以对作业的完成或任务做自定义设置或清理。
OutputCommiter 部分源码如下:
public abstract class OutputCommitter extends org.apache.hadoop.mapreduce.OutputCommitter {
public OutputCommitter() {
} public abstract void setupJob(JobContext var1) throws IOException; /** @deprecated */
@Deprecated
public void cleanupJob(JobContext jobContext) throws IOException {
} public void commitJob(JobContext jobContext) throws IOException {
this.cleanupJob(jobContext);
} public void abortJob(JobContext jobContext, int status) throws IOException {
this.cleanupJob(jobContext);
} public abstract void setupTask(TaskAttemptContext var1) throws IOException; public abstract boolean needsTaskCommit(TaskAttemptContext var1) throws IOException; public abstract void commitTask(TaskAttemptContext var1) throws IOException; public abstract void abortTask(TaskAttemptContext var1) throws IOException;
其中 setupJob在作业运行前被调用,用于初始化操作。当OutputCommitter 被设置为 FileOutputCommitter时,它会创建最终的输出目录${mapreduce.output.fileoutputformat.outputdir},并为任务的输出创建一个临时文件夹 _temporary,作为最终输出目录的子目录。
FileOutputCommitter 中setupJob() 方法源码如下:
public void setupJob(JobContext context) throws IOException {
if (this.hasOutputPath()) {
Path jobAttemptPath = this.getJobAttemptPath(context);
FileSystem fs = jobAttemptPath.getFileSystem(context.getConfiguration());
if (!fs.mkdirs(jobAttemptPath)) {
LOG.error("Mkdirs failed to create " + jobAttemptPath);
}
} else {
LOG.warn("Output Path is null in setupJob()");
} }
其中 jobAttemptPath 由 getJobAttemptPath(context) 获取,一层层往下查看此方法调用,最终可以看到FileOutputCommitter 创建的临时目录为:目标输出目录下的_temporary 子目录:
private static Path getPendingJobAttemptsPath(Path out) {
return new Path(out, "_temporary");
}
如果作业成功,则调用 commitJob() 方法。此方法会做临时文件的清理(cleanupJob()),并在最终输出目录中创建名为_SUCCESS的文件,表示Job成功执行完成。若是Job 执行失败,则被状态对象调用abortJob(),默认会调用 cleanupJob() 的方法,对临时文件进行清理。
以上提到的是Job 级别的Committer。在 Task级别,同样也有上述几种方法:
public abstract void setupTask(TaskAttemptContext var1) throws IOException; public abstract boolean needsTaskCommit(TaskAttemptContext var1) throws IOException; public abstract void commitTask(TaskAttemptContext var1) throws IOException; public abstract void abortTask(TaskAttemptContext var1) throws IOException;
其中,在 task 执行之前会调用 setupTask(),但是默认并不做任何工作。因为创建临时任务的输出路径的工作已经在setupJob() 阶段完成。方法needsTaskCommit返回是否需要task 执行提交阶段。提交阶段的工作为:将临时目录下的输出(若有)移动到最终目录。若设置为 false,则执行框架不会为任务运行分布式提交协议,也就不会执行commitTask() 或 abortTask()。当此task没有写任何输出时,FileOutputCommitter会跳过 commit (提交)阶段。
如果task成功执行,并且有输出,则会调用commitTask() 方法,(默认的实现为)将临时目录下的输出文件移动到最终目录(mapreduce.output.fileoutputformat.outputdir)。若是执行失败,则调用abortTask(),删除任务输出的临时目录及文件。
执行框架会保证一个task在有多次尝试的情况下,仅有一个task会被提交。
2. mapreduce.fileoutputcommitter.algorithm.version 1 与 2 的区别
FileOutputCommitter 有两个方法,commitTask 和 commitJob。Apache Spark 2.0 以及更高版本使用的是 Apache Hadoop 2。
Apache Hadoop 2 使用 mapreduce.fileoutputcommitter.algorithm.version 控制 commitTask 和 commitJob 如何工作。
在 Hadoop 2 中,默认的值是 1。在这种情况下,commitTask 会将 task 的输出文件从 task 的临时目录移动到 job 的临时目录下。
在所有 task 任务完成后,commitJob 将生成的数据从 job 的临时目录移动到最终的 job 目录下。这个工作在 spark 中由 driver 完成。
若是使用的是云存储(如 s3),则这个操作会消耗较长时间。会看到所有 task 已结束,但是任务仍未结束。
在设置 mapreduce.fileoutputcommitter.algorithm.version 的值为 2 后,commitTask 会将 task 生成的输出文件从 task 临时目录直接移动到 job 的最终目录。
此时,commitJob 基本无操作。
References:
[1] hadoop权威指南第4版
[2] https://docs.databricks.com/spark/latest/faq/append-slow-with-spark-2.0.0.html
Hadoop OutputCommitter的更多相关文章
- hadoop 2.7.3本地环境运行官方wordcount
hadoop 2.7.3本地环境运行官方wordcount 基本环境: 系统:win7 虚机环境:virtualBox 虚机:centos 7 hadoop版本:2.7.3 本次先以独立模式(本地模式 ...
- Hadoop官方文档翻译——MapReduce Tutorial
MapReduce Tutorial(个人指导) Purpose(目的) Prerequisites(必备条件) Overview(综述) Inputs and Outputs(输入输出) MapRe ...
- hadoop MapReduce Yarn运行机制
原 Hadoop MapReduce 框架的问题 原hadoop的MapReduce框架图 从上图中可以清楚的看出原 MapReduce 程序的流程及设计思路: 首先用户程序 (JobClient) ...
- Hadoop学习笔记: MapReduce Java编程简介
概述 本文主要基于Hadoop 1.0.0后推出的新Java API为例介绍MapReduce的Java编程模型.新旧API主要区别在于新API(org.apache.hadoop.mapreduce ...
- 更快、更强——解析Hadoop新一代MapReduce框架Yarn(CSDN)
摘要:本文介绍了Hadoop 自0.23.0版本后新的MapReduce框架(Yarn)原理.优势.运作机制和配置方法等:着重介绍新的Yarn框架相对于原框架的差异及改进. 编者按:对于业界的大数据存 ...
- Hadoop之TaskInputOutputContext类
在MapReduce过程中,每一个Job都会被分成若干个task,然后再进行处理.那么Hadoop是怎么将Job分成若干个task,并对其进行跟踪处理的呢?今天我们来看一个*Context类——Tas ...
- Hadoop基础教程之高级编程
从前面的学习中,我们了解到了MapReduce整个过程需要经过以下几个步骤: 1.输入(input):将输入数据分成一个个split,并将split进一步拆成<key, value>. 2 ...
- Hadoop学习笔记(7) ——高级编程
Hadoop学习笔记(7) ——高级编程 从前面的学习中,我们了解到了MapReduce整个过程需要经过以下几个步骤: 1.输入(input):将输入数据分成一个个split,并将split进一步拆成 ...
- OutputFormat中OutputCommitter解析
在hadoop中,由于一个Task可能由多个节点同时运行,当每个节点完成Task时,一个Task可能会出现多个结果,为了避免这种情况的出现,使用了OutPutCommitter.所以OutPutCom ...
随机推荐
- 关于微信跳转,这里有你想知道的一切weixin://dl/business/?ticket=td9cd0bf056c561fe9f56e33c61df61bf
纠结了了很久,还是放出来部分接口,相信能够看到这篇文章的人也基本都是需求比较强烈的. 京东: https://wq.jd.com/mjgj/link/GetOpenLink?rurl=http%3a% ...
- spark的运行模式
1.local(本地模式) 单机模式,通常用来测试 将spark应用以多线程方式,直接运行在本地 本地模式可以启动多个executor不过上限不能超过cpu数 2.standalone(独立模式) 独 ...
- 第九届蓝桥杯C/C++B组省赛感想
因为做了近三年的初赛题,都对了5题+,所以这次比赛前信心满满,心里想最少水个省二没问题.可我怎么知道今年的套路居然和以前不一样了!一题深搜都没有,想想一周前做的第七届初赛题,10题有3.4题深搜题. ...
- 如何正确对用户密码进行加密?转自https://blog.csdn.net/zhouyan8603/article/details/80473083
本文介绍了对密码哈希加密的基础知识,以及什么是正确的加密方式.还介绍了常见的密码破解方法,给出了如何避免密码被破解的思路.相信读者阅读本文后,就会对密码的加密有一个正确的认识,并对密码正确进行加密措施 ...
- EF(二)Model Fiirst
Model First 是先利用某些工具(如VS的EF设计器)设计出可视化的实体数据模型及他们之间的关系,然后再根据这些实体.关系去生成数据库对象及相关代码文件. 一.设计实体数据模型,生成数据库 1 ...
- poj1456
题目大意:给定一些物品以及他们的价值和时间w.t,表示物品在时间t内售出能得到w 的价值,一天只能出售一件物品,求最大利润: 非常有意思的一道并查集的思想题 首先以价值为关键字排序,类似于贪心的思想, ...
- Windbg程序调试系列5-高CPU问题分析
上篇博客中给大家分享了使用Windbg进行Live Debugging: Windbg程序调试系列4-Live Debugging 本篇中我们继续,跟大家分享常见的应用程序高CPU使用率问题分析. 先 ...
- [转载]C# TimeSpan 计算时间差(时间间隔)
TimeSpan 结构 表示一个时间间隔. 命名空间:System 程序集:mscorlib(在 mscorlib.dll 中) 说明: 1.DateTime值类型代表了一个从公元0001年1月1日 ...
- 使用OGG添加唯一标识字段到目标表
利用GoldenGate,可以获取到变更记录在源端对应的redo日志序号,redo中的地址RBA,如果源端是RAC,还可以拿到源端节点的编号,通过这3个值,可以定位该变更记录的唯一性. 这些信息,在G ...
- post请求中body数据类型
1.application/json:json格式,如下: {"input1":"xxx","input2":"ooo" ...