1.1 Mapreduce
1.1.1 逻辑过程
1.1.2 InputFormat
首相 根据context获取到split
InputSplit包含该split所在的location的信息和一个长度信息。
【FileInputFormat划分算法:mapred.min.split.size
GoalSize=FileSize/ugoalNum splitSize=Max(minSize,min(blockSize,GoalSize)),对于该Format单个文件如果小于splitSize,则必然单独一个split。】
然后创建一个Reader,该reader会将对应split里面的内容进行读取,具体操作由reader决定:
TextInputFormat
作为默认的文件输入格式,用于读取纯文本文件,文件被分为一系列以LF或者CR结束的行,key是每一行的位置偏移量,是LongWritable类型的,value是每一行的内容,为Text类型。
KeyValueTextInputFormat
同样用于读取文件,如果行被分隔符(缺省是tab)分割为两部分,第一部分为key,剩下的部分为value;如果没有分隔符,整行作为 key,value为空。
SequenceFileInputFormat
用于读取sequence file。 sequence file是Hadoop用于存储数据自定义格式的binary文件。它有两个子类:SequenceFileAsBinaryInputFormat,将 key和value以BytesWritable的类型读出;SequenceFileAsTextInputFormat,将key和value以Text类型读出。
SequenceFileInputFilter
根据filter从sequence文件中取得部分满足条件的数据,通过 setFilterClass指定Filter,内置了三种 Filter,RegexFilter取key值满足指定的正则表达式的记录;PercentFilter通过指定参数f,取记录行数%f==0的记录;MD5Filter通过指定参数f,取MD5(key)%f==0的记录。
NLineInputFormat
0.18.x新加入,可以将文件以行为单位进行split,比如文件的每一行对应一个map。得到的key是每一行的位置偏移量(LongWritable类型),value是每一行的内容,Text类型。
1.1.3 OutputFormat
主要功能为将reduce计算出的结果直接让对应的writer执行,checkOutputSpecs在Job提交前呗执行,比如File的用于检测计算的结果文件是否已经存在。
OutputCommitter用于任务的临时文件的管理。
1.1.4 Mapper
Hadoop Map/Reduce框架为每一个InputSplit产生一个map任务,而每个InputSplit是由该作业的InputFormat产生的。InputFormat在Job启动前指定。
每个Map在DataNode执行,输出键值对不需要与输入键值对的类型一致。一个给定的输入键值对可以映射成0个或多个输出键值对。通过调用context.write(word, one)可以收集输出的键值对。
应用程序可以使用Reporter报告进度,设定应用级别的状态消息,更新Counters(计数器),或者仅是表明自己运行正常。
1.1.5 Reducer
Reducer将与一个key关联的一组中间数值集归约(reduce)为一个更小的数值集。
用户可以通过 JobConf.setNumReduceTasks(int)设定一个作业中reduce任务的数目。
1.1.6 Partitioner
Partitioner用于划分键值空间(key space)。
Partitioner负责控制map输出结果key的分割。Key(或者一个key子集)被用于产生分区,通常使用的是Hash函数。分区的数目与一个作业的reduce任务的数目是一样的。因此,它控制将中间过程的key(也就是这条记录)应该发送给m个reduce任务中的哪一个来进行reduce操作。
HashPartitioner是mapreduce的默认partitioner。计算方法是
which reducer=(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks,得到当前的目的reducer。
BinaryPatitioner继承于Partitioner< BinaryComparable ,V>,是Partitioner的偏特化子类。该类提供leftOffset和rightOffset,在计算which reducer时仅对键值K的[rightOffset,leftOffset]这个区间取hash。
Which reducer=(hash & Integer.MAX_VALUE) % numReduceTasks
TotalOrderPartitioner中的Trie缺省 深度为2,即使用2+1个prefix构造Trie;每个父节点有255个子节点,对应255个ASCII字符。查找的时间复杂度为O(m),m为树的深度,空间复杂度为O(255m-1 ),可以看到,这是一种空间换时间的方案,当树深度为2时,可以最多分配255 * 255个reducer,这在绝大情况下足够了。
Hadoop 利用该技术进行排序,terasort
1.1.7 Reporter
主要用于Map 和 Reduce 计数器的获取和增加
1.1.7.1 计数器值的获取
在Hadoop作业执行时,mapper
和reducer
可使用Reporter的以下两个方法获取当前计数器。报告整个Job的Progress,以及status
public Counter getCounter(Enum<?> name);
public Counter getCounter(String group, String name);
在Hadoop作业执行完毕后,终端中会返回程序的各个计数器的值。此外,还有两种方法获取到计数器的值:
- 在jobtracker的Web页面中查看每个job和job中的每个task的计数器值。
- 使用命令获取计数器的值:
Hadoop job -counter [-counter ]
1.1.8 Context
Mapper 和Reduce 处理完数据,context.write(key, result);将结果返回给框架。
Job继承自JobContext,JobContext包含2个方法
实现该接口的类必须内部包装一个JobConf【目前只有JobConfImp】,他不提供相应的set方法。
Job提供一系列的set 以及 Job控制方法
1.1.9 ChainMapper/ChainReducer
链式Map Reduce由添加顺序指定---可以采用工作流引擎