Hadoop2.6.0官方MapReduce文档翻译 之 二

来源:互联网 发布:洛奇英雄传单机版淘宝 编辑:程序博客网 时间:2024/05/17 04:23

十、作业执行及环境: 

        MRAppMaster 执行Mapper、Reducer作业时,会将task作为它的子进程,运行在独立的jvm中。child-task 继承MRAppMaster 的运行环境。用户可以通过 mapreduce.{map|reduce}.java.opts  给 child-jvm 指定额外的设置项和在Job中设置参数(如:运行时连接器(run-time linker ) 用不标准路径(通过 -Djava.library.path=<> 来定义,如果定义中包括 @taskid@ 标志,那么它将被修改为MapReduce task的 taskid ),去搜索共享库。)
        下面的例子是一个具有多参数和替换的例子,展示了JVM的GC(垃圾回收)日志,并启动一个JVM JMK的代理密码,以便它能连接Jconsole,以查看clild的内存,线程和获取线程垃圾。还设置了map和reduce child JVM 的最大 heap-size(堆)的大小分别为512MB和1024MB。还为child-jvm添加一个额外的路径:java.library.path 。(mapreduce-site.xml文件)
<property>
  <name>mapreduce.map.java.opts</name>
  <value>
    -Xmx512M -Djava.library.path=/home/mycompany/lib -verbose:gc -Xloggc:/tmp/@taskid@.gc
    -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
  </value>
</property>

<property>
  <name>mapreduce.reduce.java.opts</name>
  <value>
    -Xmx1024M -Djava.library.path=/home/mycompany/lib -verbose:gc -Xloggc:/tmp/@taskid@.gc
    -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
  </value>
</property>

十一、内存管理:

        用户或管理员可以指定child-task启动的最大虚拟内存,和任何su-process(子进程)启动递归,用 mapreduce.{map|reduce}.memory.mb 进行设置,请注意,这里设置的值,是对每个进程的限制。mapreduce.{map|reduce}.memory.mb 应该指定为MB。还有,它的值必须大于等于Jvm的-Xmx 值,否则VM有可能无法启动。
        注:mapreduce.{map|reduce}.java.opts 仅用于对从 MRAppMaster 启动的 child tasks 配置。而守护进行的内存配置选项,是记录在Hadoop守护进程的环境配置。
        框架的某些部件的有效内存也可以配置,在map和reduce任务中,通过调整参数,影响并发操作和磁盘的数据命中率,从而影响整体性能。对文件系统的作业的Counters(总计汇报设备)进行详细监测,特别是对于从map到reduce的 byte counts(字节统计)的详细监测, 这种监测对于调整参数是非常有用的。

十二、Map的相关参数:

        由map产生的记录,将被序列化后,写入buffer metadata 则将被写入到accounting buffers 。如下列选项所描述,当序列化缓冲区或元数据超过一个阈值时,缓冲区中的内容将被分类并写入到磁盘中,同时map继续输出记录。如果在溢出过程中完全填充缓冲区,则该map线程将阻塞。当map执行完毕后,任何剩余的记录都将被写入到磁盘,所有的磁盘片段被合并为一个单独的文件。把溢出到磁盘的数量减到最小,可以减少map的执行时间,但是,更大的缓冲区同样也减少了mapper的可用内存。
参数名称
参数类型
描述
mapreduce.task.io.sort.mb
int
map产生的序列化,总计缓存的存储记录的累计大小,以MB为单位
mapreduce.map.sort.spill.percent
float
序列化缓冲区中的软限制。一旦达到,线程将开台将内容溢出到后台磁盘中。
        其他说明:
        如果超过溢出阈值或者正在溢出了,收集器将继续工作,直到溢出结束。例如,如果 mapreduce.map.sort.spill.percent  设置为0.33,当溢出开始,缓冲区的剩余部分将被填满,接下来,溢出将包括所有已收集到的记录;或者缓冲区设置为0.66,将不会产生额外的溢出。换句话说,阈值是定义触发器,而不是阻塞。
        大于序列化缓冲区的记录将首先触发溢出,然后被溢出到一个单独的文件。这是因为,它不明确这个记录是否第一时间传递给combiner中。

十三、Shuffle、Reduce的相关参数:

        如前面所述,每个reduce通过内存中Http,获取由分区器(Partitioner)指定的output,定期的将这些output进行合并,然后写入到磁盘中。如果开启了对map的output进行中间记录压缩,每个Output被解压到内存中。下列的设置项,对在reduce之前,将outputs合并到磁盘中的频率产生影响,以及对map output 到 reduce间的内存分配产生影响。
参数名称
参数类型
描述
mapreduce.task.io.soft.factorint指定同一时间,合并磁盘上分段的数量。在合并执行期间,它限制了打开文件的数量及压缩解码器的数量。如果文件的数量超过这个限制,合并器将在几个途径中继续。虽然这限制同样适用于map,但大多数jobs都应该配置,以使这个限制不可能达到。
mapreduce.reduce.merge.inmem.thresholds
int
在map outputs合并到磁盘前,提取map outputs分类到内存中的数量。像前面说的溢出阈值一样,不是定义一个分区,而是定义一个触发器。在实践中,这通常会设置得比较高(默认值1000)或者禁用(设置为0),因为在内存中合并比在磁盘中合并的代价高得多(详见本表下面的说明)。这个设置的阈值,仅对于shuffle过程中的合并频率产生影响。
mapreduce.reduce.shuffle.merge.percent
float
在内存中开始合并map outputs之前,取出map outputs的内存阈值,表示为分配给map outputs分类的内存在内存中的百分比。因为,map outputs不适合在内存中滞留,因此,设置较高的阈值,可能会降低获取和合并的并行操作。相反,高达1的阈值,对reduces的内存输入更加有效。这个设置的阈值,仅对于shuffle过程中的合并频率产生影响。
mapreduce.reduce.shuffle.input.buffer.percent
float
内存百分比,相对于在 mapreduce.reduce.java.opts中指定的最大的块大小,在shuffle过程中,能分配给map outputs的分组内存。虽然应该为框架预留一些内存,一般来说,该参数设置得足够高,去存储大量数据和大量的map outputs是有利的。
mapreduce.reduce.input.buffer.percent
float
内存百分比,相对于map outputs到reduce之间最大的块大小。当reduce开始运行时, map outputs将被合并到磁盘,直到这些记录在这个定义的资源限制以下为止。默认情况下,在reduce开始运行之前,所有的map outputs都将合并到磁盘,这样可以使reduce有最大的可用内存。内存密集型的reduces,应该调大这个值,避免读写磁盘。

        其他说明:
  • 如果一个map output大于分配给复制所有map outputs的内存25%以上,那么,它将直接被写入磁盘,而不需要经过内存。
  • Combiner运行时,关于高合并阈值和大缓存区的推理可能不成立。所有map outputs被取出之前,合并就已经开始了,Combiner当溢出到磁盘的时候,才开始运行。在某些情况下,通过占用资源的合并map outputs 而制造出小的溢出,好过去增大缓冲区的大小,更能达到最优reduce时间。
  • 当合并开始,内存中的map outputs写到磁盘同时开始reduce运行,如果中间的合并是必须的,因为存在溢出段和mapreduce.task.io.sort.factor定义的段至少会被写入磁盘,在内存中的map outputs将被合并到中间数据集中。

十四、参数配置:

        下列属性被定位于每个任务运行的作业配置。
参数名称
参数类型
描述
mapreduce.job.idString作业的id
mapreduce.job.jar
String
job.jar的工作目录
mapreduce.job.local.dir
String
job指定的共享活动空间
mapreduce.task.id
String
任务id
mapreduce.task.attempt.id
String
尝试任务id
mapreduce.task.is.map
boolean
该任务是否为map任务
mapreduce.task.partition
int
作业中,任务的id
mapreduce.map.input.file
String
map方法正在读取的文件名
mapreduce.map.input.start
long
map分割input的偏移量
mapreduce.map.input.length
long
map分割input的字节数
mapreduce.task.output.dir
String
任务的临时输出目录
        说明:
        一个流作业(streaming job)执行过程中,名称中有“mapreduce”的参数会被改变。点(.)会被变成下划线(_)。比如:mapreduce.job.id 会变成 mapreduce_job_id ,还有 mapreduce.job.jar 会变成 mapreduce_job_jar 。在流作业的mapper或reducer中,要通过带有下划线的参数名才能获取到值。

十五、Task的日志:

        task的标准输出、错误输出和系统日志,可以通过NodeManager 进行读取和直接写入到 ${HADOOP_LOG_DIR}/userlogs 路径下。

十六、Distributing Libraries(分布式库):

        DistributedCache 也能被分布在jars和本地库之间,用到map或reduce任务中。child-jvm总是有自己的当前工作目录,这目录被添加到 java.library.path and LD_LIBRARY_PATH 。因此,缓存库可以通过 system.loadlibrary 或 system.load 进行加载。如何通过分布式缓存加载共享库的详细信息,被记录在:Native Libraries 

十七、作业的提交及监测:

        Job是用户作业与 ResourceManager (资源管理器)主要接口。Job提供一个装置,用来提交作业,追踪作业执行情况,使用组件进行报告和写日志,获取MapReduce客户端机器的状态信息等等。
        作业提交过程包括:
  1. 检查Job指定的输入和输出格式;
  2. 运算Job的InputSplit的值
  3. 必要时,为Job的 DistributedCache 设置必须的统计信息;
  4. 复制Job的jar包到文件系统中MapReduce系统目录中;
  5. 提交作业给 ResourceManager 和随机监测它的状态。
        Job的历史文件也会被记录在用户指定的目录:mapreduce.jobhistory.intermediate-done-dir 和 mapreduce.jobhistory.done-dir ,作为Job的默认输出目录。
        用户可以用下面的命令行查看指定目录中的历史日志的概要信息:(未试成功
        $ mapred job -history output.jhist 
        该命令将打印作业的详情,作业失败和死亡的提示详情。
        作业的更多详情,如执行成功的任务和为每个任务的尝试,可以通过下面的命令来查看:(未试成功
        $ mapred job -history all output.jhist 
        一般情况下,用户利用Job来创建应用程序,描述Job的各个方面,提交Job,并监测其执行情况。

十八、Job Control:

        用户可能需要连接多个MapReduce Job 一起来完成一系列复杂的任务。这是相当容易的,因为Job的输出一般都存储在分布式文件系统中,反过来说,Job的output可以作下个任务的输入。
        那么,这也意见着,每个客户机器,都需要确保Job已经执行完毕(不管是成功或者失败)。作业的控制方式有如下两种:
  1. Job.submit()  :  将作业提交给集群,并立即返回。
  2. Job.waitForCompletion(boolean)   :  将作业提交给集群,并等待作业完成。

十九、Job Input:

        InputFormat 描述了一个MapReduce作业的输入规范。MapReduce框架依赖于InputFormat进行工作:
  1. 校验输入是否规范;
  2. 将输入文件进行逐一的拆分成,拆分成符合框架逻辑的InputSplit实例,然后每一个InputSplit实例都被分配到一个独立的Mapper。
  3. RecordReader 实现了从符合框架逻辑的InputSplit实例收集输入的记录,提供给Mapper进行处理。
        InputFormat的默认实现,通常是FileInputFormat的子类,对输入的文件(以byte为单位)进行分割,分割为符合框架逻辑的InputSplit实例。以文件系统的block大小,作为输入文件的分割界线。如果分隔线以下的文件,要进行分割,则可以通过mapreduce.input.fileinputformat.split.minsize 进行设置。
        显然,遵守记录边界,基于输入文件的大小进行逻辑分割,是不以支持许多应用程序的。在这种情况下,应用程序应该实现RecordReader ,负责关联记录边界和提出一个面向记录逻辑分割的视图给每个任务。
        TextInputFormat是默认的InputFormat
        如果Job的InputFormat是由TextInputFormat提供的,框架检查文件是.gz的扩展名文件,则会自动使用合适的CompressionCodec,对文件进行自动解压。然而,需要特别指明的是,.gz的压缩文件,是不能进行分割的,每个压缩文件只能由一个Mapper进行处理。

19.1 InputSplit:

        InputSplit代表一个Mapper对数据进行处理。
        通常情况下,InputSplit提供了一个面向字节的输入,负责对RecordReader 进行处理,并提出一个面向记录的视图。
        FileSplit是默认的InputSplit。它把输入的文件路径设置到mapreduce.map.input.file ,用于进行逻辑分割。

19.2 RecordReader:        

        RecordReader从一个InputSplit中读取<key,value>。
        通常RecordReader把input转换成面向字节的输入,然后提供给InputSplit,再提供一个面向记录的输入给Mapper实例进行处理。从而RecordReader承担起从记录中提取键值对的任务。

二十、Job Output:

        OutputFormat 描述了MapReduce作业的输出规范。
        框架依赖OutputFormat进行工作的格式为:
  1. 输出规范性校验;例如:检查输出目录是否存在。(输出目录不能存在)   
  2. 提供RecordWriter实例,将Job的结果写到outputs文件中,并存放到分布式文件系统中;
        TextOutputFormat是默认的 OutputFormat.

20.1 OutputCommitter: 

        OutputCommitter描述一个已提交的MapReduce作业的任务输出。
        MapReduce框架job依赖的OutputCommitter,可以用来:
  1. 在初始化过程中,设置Job。例如,在job初始化过程中,为Job创建临时输出目录。当Job处于预备(PREP)状态和所有的task都初始化完毕后,通过一个单独的task来配置Job。一旦配置job的task执行完成,则Job的状态会变为运行中(RUNNING)。
  2. Job执行完毕,清理Job。例如,Job执行完毕后,删除掉为Job创建的临时输出目录。Job清理是由一个单独的task来执行的,在job结束后被执行。Job宣告执行完毕的状态有(SUCCEDED,FAILED,KILLED),然后完成Job的清理工作。
  3. 设置task的临时输出。task初始化期间,task配置将作为相同任务的一部分,在初始化过程中完成task设置。
  4. 检查task是否需要进行提交。这样是为了避免无用的提交。如果一个task不需要提交,那 就不提交。
  5. 提交task的输出。task一旦完成,如果有输出的,那么task会提交输出。
  6. 放弃提交任务。如果task被标志为:failed,killed,那么task的输出将被清理掉。如果task清除失败(发生异常块),那么将会启动一个单独的task(具有相同的尝试ID),继续完成task的清理工作。
        FileOutputCommitter 是默认的 OutputCommitter。在NodeManager中,Job的设置和清除都会占用map或reduce的容器,不管是哪一个都是有用的。JobCleanup task    TaskCleanup task    JobSetup task    拥有最高的优先级,他们三个的优化级,按照该顺序。

20.2 Task Side-Effect(副作用) Files :

        一些应用程序,任务组件需要创建或写入数据到站点中的目录,而这个目录与最终job的输出目录又一样。两个相同实例的Mapper,Reducer同时运行(例如:推测作业),它们可能打开或写入分布式文件系统中的相同目录,在这种情况下可能会出现问题。因此,应用程序不得不为每一个尝试作业定义一个唯一的名称(使用attemptid,则表示为: attempt_200709221812_0001_m_ 000000 _0),而不是为每个作业。
        框架为了避免这种问题,当OutputCommitter是FileOutputCommitter的时候,保持一个特殊的输出${mapreduce.output.fileoutputformat.outputdir}/_temporary/_${taskid},子目录可以通过${mapreduce.task.output.dir}为每个尝试作业在文件系统中建立其对应的输出目录。在成功完成尝试任务后 ,在${mapreduce.output.fileoutputformat.outputdir}/_temporary/_${taskid}中的文件将被移到${mapreduce.output.fileoutputformat.outputdir}目录中。当然,框架会丢弃掉执行失败的尝试作业其对应目录中的文件,这个过程对于应用程序是完全透明的。
        在task执行过程中,通过FileOutputFormat.getWorkOutputPath(Conext),应用程序的application-writer,能够利用这个特性,在${mapreduce.task.output.dir} 目录下面,创建任务需要的任何side-files。框架将促使他们完成尝试任务,从而消除需要为每个尝试任务指定一个唯一目录的需要。
        注意事项:
        特定的尝试任务执行期间的${mapreduce.task.output.dir}的值,事实上是${mapreduce.output.fileoutputformat.outputdir}/_temporary/_{$taskid}值,这个值是由框架来设置的。所以,刚刚通过FileOutputFormat.getWorkOutputPath(Conext)返回目录来创建的任何一个side-files,都是从MapReduce 作业利用这一特性而得来的。
        整个讨论过程,适用于没有Reducer的Maps的输出,在这情况下,将直接写入到HDFS中。
18.3 RecordWriter:
        RecordWriter写入<key,value>键值对到输出文件中。
        RecordWriter实现将Job的导出写到文件系统中。

二十一、Other Useful Features(其他有用的特性):

21.1 Submitting Jobs to Queues (提交Job到队列中):

        用户可以把Job提交到队列(Queues)中。Queues,是一个Job集合,允许系统提供特别的功能。例如,Queues用ACLs来控制,哪些用户可以向它提交作业。Queues期待被作为Hadoop的主要调度器。Hadoop配置了一个叫“default”的强制queue。Queue的名称定义在mapreduce.job.queuename 直接下层property 节点中(Hadoop site configuration文件中)。有些作业调度器支持多个Queues,如Capacity Scheduler(容量调度器)。
        一个Job要定义queue,它通过mapreduce.job.queuename属性来提交,或者通过Configuration.set(MRJobConfig.QUEUE_NAME, String)应用程序接口进行提交。设置Queue的名称是可选的。如果一个作业被提交时没有指定queue名称,那么该Job将被提交到“default”queue。

21.2 Counters :        

        Counters 代表全局的计数器,由MapReduce框架或应用程序自行定义。每个Counter可以是任何的枚举类型。某个枚举类型的都在Counters.Group这个类型组中。在map、reduce方法中,应用程序可以通过Counters.incrCounter(Enum, long) 或者Counters.incrCounter(String, String, long) 来定义任意计数器(任意枚举型的计数器)和更新计数器。这些Counter作为全局计数器被框架进行汇总。

21.3 DistributedCache :

DistributedCache 使分发应用程序指定的,大的,只读的文件更有效。DistributedCache 是一个由MapReduce框架提供的设备,用于缓存应用程序需要的文件(text,archives,jars等等)。
        在Job中,应用程序可以通过Url(hdfs://)指定需要被缓存的文件。DistributedCache 会假定该文件已存在文件系统中。在Job任务在节点上运行之前,框架将会把task所需的文件复制到该slave节点中。它的功效源于一个事实,在slave节点中,每个job只能复制一次文件,它能缓存未归档的文件。DistributedCache会跟踪文件修改的时间戳。显示,在Job运行过程中,缓存文件不应该被应用程序及外部修改。
        DistributedCache能够被用于分发简单的,只读的数据或者文本文件和其他复杂类型的文件,如:archives,jars等等。在slave节点中,archives(zip,tar,tgz,tar.gz文件)都是未归档文件。文件具有执行权限集。
        通过设置mapreduce.job.cache.{files|archives}属性,files或者archives能进行分布缓存。如果有多个文件或者归档文件想进行分布缓存,可能通过“,”逗号分隔字符串路径来指定。也可以通过应用程序接口: Job.addCacheFile(URI)/ Job.addCacheArchive(URI) and Job.setCacheFiles(URI[])/ Job.setCacheArchives(URI[])  来设置,这里面的URI为 hdfs://host:port/absolute-path#link-name。在流作业中,还可以通过命令行:-cacheFile/-cacheArchive来设置。
        DistributedCache也可以作为一种基本的软件分发机制,用于map、reduce作业中。它能被用于jar包和本地库。Job.addArchiveToClassPath(Path) 、Job.addFileToClassPath(Path) 应用程序接口,能用于缓存文件或者Jar包,也可以向child-jvm的classpath 添加。同样也可以通过配置文件 mapreduce.job.classpath.{files|archives}实现。同样的缓存文件,被系统连接到task的工作目录,能被用于分布本地库和加载。

23.3.1 Private and Public DistributedCache Files:

        DistributedCache文件可以是公有的,也可以是私有的,这决定了这些文件如何在slave节点间共享。
  • 私有的:DistributedCache文件被缓存在本地目录中,供私人的Job使用。这些文件共享仅给指定用户的所有的task和jobs,并不能供slaves上的其他用户使用。借用文件系统的权限来把文件变成私有的文件,这个文件系统一般为HDFS。
  • 公有的:DistributedCache文件被缓存在全局的目录中,文件对于所有用户都是公开的,可见的。这些文件能供slaves上所有用户的task,job使用。借用文件系统的权限来把文件变成公有的文件,这个文件系统一般为HDFS。如果用户打算使一个文件变为公有的,那么文件权限设置为word readable,而且目录必须设置为executable。

23.4 Profiling(分析器):

        分析器一个通用的程序,以获取一个有代表性(2或3个)样本,为maps和reduces的样本而内置的java工具。用户可以指定系统是否需要为一些任务收集探测信息,可以通过配置文件属性来指定:mapreduce.task.profile。这个值也可以通过应用程序API来设置:Configuration.set(MRJobConfig.TASK_PROFILE, boolean)。如果设置为ture,作业启用分析器,探查信息存储在用户日志目录中。默认情况下,作业不启用分析器。
        一旦用户启用分析器,就可以通过mapreduce.task.profile.{maps|reduces}属性,来设置分析器的分析范围。这个值也可以通过应用程序API来设置:Configuration.set(MRJobConfig.NUM_{MAP|REDUCE}_PROFILES, String)。
默认情况下,指定的范围是0-2。
        用户可以指定分析器的参数,通过配置属性:mapreduce.task.profile.params。这个值也可以通过应用程序API来设置:Configuration.set(MRJobConfig.TASK_PROFILE_PARAMS, String)。如果该字符串包含"%s",则将在任务运行时替换分析输出文件的名称。这些参数将被传递给task child JV 命令行上。分析器参数的默认值是:-agentlib:hprof=cpu=samples,heap=sites,force=n,thread=y,verbose=n,file=%s。

23.5 Debugging:

        MapReduce框架提供一个设备用于运行用户提供调试的脚本。以处理任务日志为例,当一个task运行失败时,用户可以运行一下调试脚本。脚本是获得任务的stdout和stderr输出,系统日志和jobconf。从调试脚本的stdout和stderr输出显示在控制台诊断器上,也被视为Job的UI的一部分。下面的章节,接讨论用户如何提交一个调试脚本。脚本文件需要分发并提交给框架。
        如何分发脚本文件:
        用户需要使用distributedcache分发和使用脚本文件。
        如何提交脚本:
        提交调试脚本的快速方法是为属性设置值:mapreduce.map.debug.script 和 mapreduce.reduce.debug.script ,分别用于调试map和reduce。这些属性也可以通过应用程序接口来设置:Configuration.set(MRJobConfig.MAP_DEBUG_SCRIPT, String) 和Configuration.set(MRJobConfig.REDUCE_DEBUG_SCRIPT, String)。如果在流工作中,也可以通过命令行来设置:-mapdebug 和 -reducedebug 。
        脚本的参数是任务的stdout,stderr,syslog和jobconf文件。
        调试命令,运行在MapReduce任务失败的节点,是:
        $script $stdout $stderr $syslog $jobconf

23.6 Data Compression(数据压缩):        

        Hadoop MapReduce为application-writer提供了一个为map-outputs和job-outputs指定压缩算法的设备。框架还附带了CompressionCodec实现的一个zlib压缩算法。gzip, bzip2, snappy, and lz4 格式的文件都支持。
        Intermediate Outputs:
        通过应用程序API:Configuration.set(MRJobConfig.MAP_OUTPUT_COMPRESS, boolean),应用程序可以控制对map-outputs进行压缩,通过应用程序API:Configuration.set(MRJobConfig.MAP_OUTPUT_COMPRESS_CODEC, Class) ,启用压缩算法CompressionCodec。   
        Job Outputs:
        通过应用程序API:FileOutputFormat.setCompressOutput(Job, boolean),应用程序可以控制对 job-outputs进行压缩。通过应用程序API:FileOutputFormat.setOutputCompressorClass(Job, Class),可以启用压缩算法:CompressionCodec。
        如果Job-outputs存储在 SequenceFileOutputFormat中,则需要通过应用程序API:SequenceFileOutputFormat.setOutputCompressionType(Job, SequenceFile.CompressionType),指定SequenceFile.CompressionType (i.e. RECORD / BLOCK - defaults to RECORD)。
        Skipping Bad Records(跳过不良计录):
        Hadoop 提供一个设置项,明确的设置了不良的输入记录,当map处理输入记录时,这些不良的输入记录将被跳过。应用程序可以通过SkipBadRecords类,来控制这个特性。此特性可以用于在明确map任务遇到损坏的输入记录的时候。这通常是由于map方法中有bug所导致的。通常情况下,用户必须修复这些bug。然而,这些bug有时候是无法修复的。例如,有些bug存在于第三方代码库,第三方代码库的代码是无法修改的。在这种情况下,task失败是必须的,即使是多次的尝试,job最终还是失败。用了这个特性,仅仅是丢弃一小部分的不良数据,对一个应用程序来讲是可以忽略的(对非常大的数据进行统计的情况下)。
        默认情况下该特性是开启的。要开启,需要指定: SkipBadRecords.setMapperMaxSkipRecords(Configuration, long) 和 SkipBadRecords.setReducerMaxSkipGroups(Configuration, long)。启用这个特性,框架会在一定数量的map task失败后,进入“跳跃模式”。更多的详情见:SkipBadRecords.setAttemptsToStartSkipping(Configuration, int)。在“跳跃模式”下,map任务,将保持对其范围内的数据的处理。要做到这一点,该框架要依靠Counter(计数器)的处理结果。可以查看:SkipBadRecords.COUNTER_MAP_PROCESSED_RECORDS 和SkipBadRecords.COUNTER_REDUCE_PROCESSED_GROUPS 了解更多详情。这个Counter可以令框架知道有多少记录处理成功,多少范围的记录处理失败。再进一步尝试后,这些范围的记录就会被丢弃。
        被丢弃的记录的数量依据应用程序的Counter频繁的处理记录。推荐,Counter在每个记录被处理完成后,再进行增加计数。在一些批处理应用程序中,有可能不会出现这种情况。在这种情况下,框架可以跳过不良记录周围的记录。用户可控制跳过记录的数量:SkipBadRecords.setMapperMaxSkipRecords(Configuration, long) 和SkipBadRecords.setReducerMaxSkipGroups(Configuration, long) 设置。框架将通过折半搜索,尝试缩小跳过的记录的数量。跳过过的记录被分为两半,先执行一半。在失败后,框架就能知道哪一半包含不良记录。这个任务将被重复执行,直到不良记录被找到或所有尝试任务都耗尽。想要增加尝试任务的数量,可以设置: Job.setMaxMapAttempts(int) and Job.setMaxReduceAttempts(int)。
        跳过的文件会被写到HDFS中的序列格式文件中,以便后来进行分析。存储位置可以设置:SkipBadRecords.setSkipOutputPath(JobConf, Path)。

23.7 实例 WordCount v2.0:

        这个例子,应用了到目前为止,我们讨论过的框架的很多个特性。首先,HDFS需要启动,处于运行中。特别是对distributedcache相关特征。因此,它只适用于伪分布式或完全分布式的Hadoop的环境。
0 0
原创粉丝点击