hadoop--之mapreduce框架流程
来源:互联网 发布:下载mp4连续剧软件 编辑:程序博客网 时间:2024/05/17 17:17
1.5 进度和状态的更新
一个作业和每个任务都有一个状态信息,包括:作业或任务的运行状态(running, successful, failed),map和reduce的进度,计数器 值,状态消息或描述。
这些信息通过一定的时间间隔由child JVM –> task tracker –> job tracker汇聚。job tracker将产生一个表明所有运行作业及其任务状态 的全局试图。你可以通过Web UI查看。同时JobClient通过每秒查询jobtracker来获得最新状态。
Child JVM有独立的进程每隔三秒检查任务更新标志,如果有更新就报告给tasktracker
tasktracker每隔5秒给jobtracker发心跳
job tracker合并这些更新,产生一个表明所有运行作业及其状态的的全局视图
job client 通过每秒轮询Jobtracker来接收最新消息
1.6 作业的完成
1.7 作业的失败
2. 作业的调度
默认调度器 – 基于队列的FIFO调度器
公平调度器(Fair Scheduler)- 每个用户都有自己的作业池,用map和reduce的任务槽数来定制作业池的最小容量,也可以设置每个池的权重。Fair Scheduler支持抢占,如果一个池在特定的一段时间内未得到公平的资源共享,它会中止运行池得到过多资源的任务,以便把任务槽让给运行资源不足的池。启动步骤:
1) 拷贝contrib/fairscheduler下的jar复制到lib下;
2) mapred.jobtracker.taskScheduler = org.apache.hadoop.mapred.FairScheduler
3) 重启节点hadoop
能力调度器(Capacity Scheduler)-
4. 任务的执行
Hadoop发现一个任务运行比预期慢的时候,它会尽量检测,并启动另一个相同的任务作为备份,即“推测执行”(speculative execution)。
推测执行是一种优化措施,并不能使作业运行更可靠。默认启用,但可以单独为map/reduce任务设置,mapred.map.tasks.speculative.execution和mapred.reduce.tasks.speculative.execution。开启此功能会减少整个吞吐量,在集群中倾向于关闭此选项,而让用户根据个别作业需要开启该功能。
Hadoop为每个任务启动一个新JVM需要耗时1秒,对于大量超短任务如果重用JVM会提升性能。当启用JVM重用后,JVM不会同时运行多个任务,而是顺序执行。tasktracker可以一次启动多个JVM然后同时运行,接着重用这些JVM。控制任务重用JVM的属性是mapred.job.reuse.jvm.num.tasks,它指定给定作业每个JVM运行的任务的最大数,默认为1,即无重用;-1表示无限制即该作业的所有的任务都是有一个JVM。
在map/reduce程序中,可以通过某些环境属性(Configuration)得知作业和任务的信息。
mapred.job.id 作业ID,如job_201104121233_0001
mapred.tip.id 任务ID,如task_201104121233_0001_m_000003
mapred.task.id 任务尝试ID,如attempt_201104121233_0001_m_000003_0
mapred.task.partition 作业中任务的ID,如3
mapred.task.is.map 此任务是否为map任务,如true
hadoop1.x Mapreduce类型和格式2. 输入格式
2.1输入分片与记录
一个输入分片(split)是由单个map处理的输入块(分片个数即map所需的tasktracker个数),每个分片包含若干记录(key+value),map函数依次处理每条记录。输入分片表示为InputSplit接口,其包含一个以字节为单位的长度和一组存储位置,分片不包含数据本身,而是指向数据的引用。
InputSplit是由InputFormat创建的,一般无需应用开发人员处理。InputFormat负责产生输入分片并将它们分割成记录。
1) JobClient调用InputFormat.getSplites()方法,传入预期的map任务数(只是一个参考值);
2)InputFormat计算好分片数后,客户端将它们发送到jobtracker,jobtracker便使用其存储位置信息来调度map任务从而在tasktracker上处理这些分片数据。
3)在tasktracker上,map任务把输入分片传给InputFormat的getRecordReader()方法来获得这个分片的RecordReader;RecordReader基本上就是记录上的迭代器,map任务用一个RecordReader来生成记录的键值对,然后在传给map函数。
2.2 FileInputFormat
输入路径可由多个函数FileInputFormat.addInputPath()指定,还可以利用FileInputFormat.setInputPathFilter()设置过滤器。输入分片的大小有上个属性控制:分片最小字节数,分片最大字节数和HDFS数据块字节数。
mapred.min.split.size, mapred.max.split.size, dfs.block.size
计算公式是:
max(minSplitSize, min(maxSplitSize, blockSize))
没有特殊需求,应该尽量让分片大小和数据块大小一致。如果HDFS中存在大批量的小文件,则需要使用CombineFileInputFormat将多个文件打包到一个分片中,以便mapper可以处理更多的数据。一个可以减少大量小文件的方法(适合于小文件在本地文件系统,在上传至HDFS之前将它们合并成大文件)是使用SequenceFile将小文件合并成一个或多个大文件,可以将文件名作为键,文件内容作为值。
有时候不希望输入文件被切分,只需覆盖InputFormat的isSplitable()方法返回false即可。
有时候map程序想知道正在处理的分片信息,可以通过Configuration中的属性得到,包括map.input.file(正在处理的输入文件的路径),map.input.start(分片开始处的字节偏移量), map.input.length(分片的字节长度)。
有时候map想访问一个文件的所有内容,需要一个RecordReader来读取文件内容作为record的值。可行的方法是实现一个FileInputFormat的子类,将文件标记为不可切分,同时指定一个特定的RecordReader;该RecordReader只是在第一次next()时返回文件的内容。
2.3 文本输入
TextInputFormat是默认的InputFormat。每条记录是一行输入。键是LongWritable类型,存储该行在整个文件中的字节偏移量;值是这行的内容,不包括任何行终止符(换行符和回车符),Text类型。由于一行的长度不定,所以极易出现split分片会跨越HDFS的数据块。
KeyValueTextInputFormat将文件的每一行看作一个键值对,使用某个分界符进行分隔,比如制表符。Hadoop默认输出的TextOutputFormat格式即键值对为一行组成一个文件,处理这类文件就可以使用键值文本输入格式。
NLineInputFormat可以保证map收到固定行数的输入分片,键是文件中行的字节偏移量,值是行内容。默认为1,即一行为一个分片,送给每个map。
2.4 二进制输入
SequenceFileInputFormat存储二进制的键值对的序列。顺序文件SequenceFile是可分割的,也支持压缩,很符合MapReduce数据的格式。
2.5 多种输入
Hadoop也支持在一个作业中对不同的数据集进行连接(join),即定义多个不同的数据输入源,每个源对应不同的目录、输入格式和Map函数。
MultipleInputs.addInputpath(conf, inputPath, TextInputFormat.class, MaxTemperatureMapper.class);
2.6 数据库输入和输出
DBInputFormat用于使用JDBC从关系数据库中读取数据,但只适合少量的数据集。如果需要与来自HDFS的大数据集连接,要使用MultipleInputs。
在关系数据库和HDFS之间移动数据的另一个方法是Sqoop。
HBase和HDFS之间移动数据使用TableInputFormat和TableOutputFormat。
3. 输出格式
TextOutputFormat是默认的输出格式,它把每条记录写为文本行,键和值可以是任意类型。
SequenceFileOutputFormat将输出写入一个顺序文件,是二进制格式。MapFileOutputFormat把MapFile作为输出,键必须顺序添加,所以必须确保reducer输出的键已经排好序。
FileOutputFormat及其子类产生的文件放在输出目录下,每个reducer一个文件并且文件由分区号命名,如part-00000,part-00001等。有时候需要对文件名进行控制,或让每个reduce输出多个文件,则可使用MultipleOutputFormat和MultipleOutputs类。
MultipleFileOuputFormat可以将数据写到多个文件,关键是如何控制输出文件的命名。它有两个子类:MultipleTextOutputFormat和MultipleSequenceFileOutputFormat。在使用多文件输出时,只需实现它们任何一个的子类,并覆盖generateFileNameForKeyValue()返回输出文件名。
MultipleOutputs类不同的是,可以为不同的输出产生不同的类型。
MultipleOutputs.addMultiNameOutput(conf, “name”, TextOutputFormat.class, KeyClass, valueClass);
新版本Hadoop中上述两个多输出类也合并。
FileOutputFormat的子类会产生输出文件,即使文件是空的。可以使用LazyOutputFormat来去除空文件。
这章主要总结MapReduce的高级特性,包括计数器,数据集的排序和连接。
hadoop1.x Mapreduce特性
1. 计数器
计数器是一种收集作业统计信息的有效手段,由于质量控制或应用统计。计数器还可辅助诊断系统故障。
Hadoop为每个作业维护若干内置计数器,以描述该作业的各项指标。计数器由关联任务维护,并定期(3秒)传到tasktracker,再由tasktracker传给jobtracker(5秒,心跳)。一个任务的计数器值每次都是完整传输的,而非增量值。
MapReduce允许用户编写程序定义计数器,一般是由一个Java枚举(enum)类型定义。枚举类型的名称即计数器组名称,枚举类型的字段即计数器名称。计数器在作业实例级别是全局的,MapReduce框架会跨所有的map和reduce来统计这些计数器,并在作业结束时产生一个最终的结果。
enum Temperature {
MISSING, MAlFORMED
}
…
context.incrCounter(Temperature.MISSING, 1);
MapReduce同时支持非枚举类型的动态计数器。
context.incrContext(String group, String counter, int amount);
计数器可以通过很多方式获取,Web界面和命令行(hadoop job -counter指令)之外,用户可以用Java API获取计数器的值。
RunningJob job = jobClient.getJob(JobID.forName(id));
Counters counters = job.getCounters();
long missing = counters.getCounter(MaxTemperatue.Temperature.MISSING);
2. 排序
排序是MapReduce的核心技术,尽管应用程序本身不需要对数据排序,但可以使用MapReduce的排序功能来组织数据。默认情况下,MapReduce根据输入记录的键对数据排序。键的排列顺序是由RawComparator控制的,规则如下:
1)若属性mapred.output.key.comparator.class已设置,则使用该类的实例;
2)否则键必须是WritableComparable的子类,并使用针对该键类的已登记的comparator;
3)如果还没有已登记的comparator,则使用RawComparator将字节流反序列化为一个对象,再由WritableComparable的compareTo()方法进行操作。
全排序
如何用Hadoop产生一个键全局排序的文件?(最好的回答是使用Pig或Hive,两者均可使用一条指令进行排序)
大致方法是,想办法创建一系列排好序的文件,而且这些文件直接也是排序的,比方说第一个文件的值都不第二个文件的值小,则简单的拼装这些文件就可以得到全局排序的结果。问题是如何划分这些文件,并把原始文件的值放入这些排序的文件中?可以使用map的partition来将某一范围的键放入对于的reduce,每个reduce的输入可以保证已排序(局部排序),默认直接输出到part-000×,那所有这些输出组合成一个文件就是全局排序的。为了得到合适的范围,需要对所有输入数据进行统计,实际做法是通过抽样,Hadoop提供InputSampler和IntervalSampler。使用抽样函数事先对input数据进行抽样,得到抽样范围,然后将范围写入分布式缓存,供集群上其它任务使用。
DistributedCache.addCacheFile(cacheFile, conf);
DistributedCache.createSymlink(conf);
辅助排序
MapReduce框架在记录达到reducer之前按键对记录排序,但键所对应的值并没有排序。大多情况下不需考虑值在reduce函数中的出现顺序,但是,有时也需要通过对键进行排序和分组等以实现对值的排序。
例子:设计一个MapReduce程序以计算每年最高气温。
1)使用组合键IntPair,将年份和气温都作为键;
2)按照年份来分区和分组,但排序需要按照年份升序和气温降序。
conf.setPartitionerClass();
conf.setOutputKeyComparatorClass();
conf.setOutputValueGroupingComparator();
3 连接
MapReduce能执行大型数据集间的“连接”操作。
Map端连接指在数据到达map函数之前就执行连接操作。为达到此目的,各map的输入数据必须先分区并且以特定方式排序。各个数据集被划分成相同数量的分区,并且均按相同的键(连接键)排序。同一键的所有记录均会放在同一分区之中。
map连接操作可以连接多个作业的输出,只要这些作业的reduce数量相同,键相同,并且输出文件是不可切分的(如小于HDFS块大小,或gzip压缩)。利用org.apache.mapred.join包中的CompositeInputFormat类来运行一个map端连接,其输入源和连接类型(内连接或外连接)可以通过一个连接表达式进行配置。
Reduce连接不要求数据集符合特定结构,因此比Map连接更为常用。但是,由于数据集均经过mapReduce的shuffle过程,所以reduce端连接的效率往往更低一些。基本思路是mapper为各个记录标记源,并且使用连接键作为map输出键,使键相同的记录放在同一个reducer中。
1)可以使用MultipleInputs来解析和标注各个源;
2)先将某一个数据源传输到reduce。举天气数据为例,气象站信息(气象站id和名字)以气象站ID+“0”为组合键,名字为值,但是按照ID来分区和分组;气象站天气情况(气象站id,时间和气温)以气象站ID+“1”为组合键,气温为值,但是按照ID来分区和分组。两组数据经过不同的map之后,具有相同的ID的记录被合并作为一个记录输入reduce程序,值列表中的第一个是气象站名称,其余的记录都是温度信息。reduce程序只需要取出一个值,并将其作为后续每条输出记录的一部分写到输出文件即可。
conf.setPartitionerClass();
conf.setOutputValueGroupingComparator(Textpair.FirstComparator.class);
4 边数据分布(side data)
边数据是作业所需的额外的只读数据,已辅助处理主数据集。面临的挑战是如何让所有的map和reduce都能方便高效地使用边数据。
1)如果仅需向任务传递少量元数据,则可以通过Configuration来设置每个job的属性,则map/reduce可以覆盖configure()方法来获取这些元数据值。如果你设置的值是复杂对象,则需要处理序列化工作。在几百个作业同在一个系统中运行的情况下,这种方法会增多内存开销,而且元数据信息在所有节点都缓存,即使在不需要它的jobtracker和tasktracker上。
2)针对小数据量边数据的常用办法是将在map/reduce数据缓存在内存中,并通过重用JVM使tasktracker上同一个作业的后续任务共享这些数据。
3)分布式缓存 (-files, -archives)
a)启动作业时,使用files或archives传入元数据文件路径,
%hadoop jar job.jar MaxTempratureSample –file input/metadata/stations-fixed-width.txt input/all output
b)当tasktracker获得任务后,首先将jobtracker中的上述文件复制到本地磁盘,具体在${mapred.local.dir}/taskTracker/archive,缓存的容量是有限的,默认10GB,可以通过local.cache.size来设置。
c)在map/reduce程序中,直接读取“stations-fixed-width.txt”文件。同时可以通过JobConf.getLocalCacheFiles()和JobConf.getLocalCacheArchives()来获取本地文件路径的数组。
5 MapReduce类库
Hadoop还提供了一个MapReduce类库,方便完成常用的功能。
ChainMapper, ChainReducer 在一个MapReduce中运行多个mapper或reducer。(M+RM*)
IntSumReducer, LongSumReducer 对各键的所有整数值进行求和操作的reducer
TokenCounterMapper 输出各单词及其出现的次数
RegexMapper 检查输入值是否匹配某正则表达式,输出匹配字符串和计数器值
- hadoop--之mapreduce框架流程
- Hadoop学习之MapReduce框架
- Hadoop组件之MapReduce框架
- Hadoop之MapReduce计算框架
- Hadoop之MapReduce程序开发流程
- Hadoop入门之Mapreduce部分流程解析
- Hadoop入门之Mapreduce流程Shuffle过程
- Hadoop学习之MapReduce运行流程
- Hadoop之MapReduce框架心跳机制分析
- Hadoop 之 MapReduce 框架演变详解
- Hadoop学习之MapReduce框架详解
- hadoop--之YARN框架流程
- hadoop mapreduce执行流程
- hadoop mapreduce执行流程
- Hadoop MapReduce 技术流程
- Hadoop MapReduce框架详解
- hadoop:mapreduce框架详解
- Hadoop计算框架Mapreduce
- MATLAB利用双下标提取矩阵元素
- word中设置多级标题
- codeforces round#353 trians and statistic dp+贪心+线段树
- 从数据结构角度分析foreach效率比for循环高的原因
- g_pIMalloc 全局变量
- hadoop--之mapreduce框架流程
- 子查询和连接
- 创建maven项目 并搭建简单的springMVC
- redis使用watch完成秒杀抢购功能
- Block
- IDEA之svn
- Unity3D协程进阶-原理剖析
- Linux常用命令
- 浅谈CSS选择器中的空格