1. 计数器
收集作业统计信息,可辅助诊断系统故障,Hadoop作业的内置计数器包括map和reduce输入/输出/跳过的记录,溢出记录,文件系统读写的字节以及启动或失败的map或reduce等。用户可自定义计数器,多个计数器由一个Java枚举类型来定义,以便对计数器分组。枚举类型的名称即为组名,字段为计数器名。
enum Group {
counter
}
reporter.incrCounter(Group.counter, 1)
public void incrCounter(String group, String counter, long amount) // 动态计数器,不需要枚举类型,更方便
2. 排序部分排序:默认情况下,MapReduce根据输入记录的键对数据集排序,如调用默认的HashPartitioner分区,分区内记录根据键进行排序,由RawComparator控制。【按键执行查找操作,在多文件情况下,基于MapFile具有更高效率,MapFileoutputFormat提供了getReader()和getEntry()方法】
全排序:将数据划分到不同的有序区域,区域内排好序后,合并区域即可得到全局排序结果。如何划分?才能是每个分区所含记录数大致相等?可以对键空间进行采样,获得键的近似分布,由此构建较均匀分区。Hadoop内置了若干采样器:InputSampler类实现了Sampler接口,通过InputSampler的静态方法writePartitionFile调用以创建一个顺序文件来存储定义分区的键。另一个内置采样器是IntervalSample,以一定间隔定期从划分中选择键。
辅助排序:记录在达到reducer前按键排序,但对应值并未排序,可以使用组合键方法:定义包括自然键和自然值的组合键-->键的comparator根据组合键对记录进行排序-->针对组合键的partitioner和分组comparator在进行分区和分组时均只考虑自然键。
void map(key, value, ...) {
...
output.collect(new IntPair(key, value), NullWritable.get()); // 利用IntPair定义组合键
}
class FirstPartitioner ...{ // 自定义partitioner
public int getPartition(IntPair key, NullWritable value, int numParatitions) {
// 根据ket.getFirst()决定分区
}
}
class KeyComparator ...{
public int compare(WritableComparable w1, WritableComparable w2) {
// 根据组合键排序
}
}
class GroupCpmparator ... {
public int compare(WritableComparable w1, WritableComparable w2) {
// 根据自然键排序
}
}
public void run() {
...
conf.setPartitionerClass(FirstPartitioner.class);
conf.setOutputKeyComparatorClass(KeyComparator.class);
conf.setOutputValueGroupingComparator(GroupComparator.class); // 按自然键分组
...
}
3. 连接
MapReduce能执行大型数据集间的join操作,其具体实现取决于数据集的规模及分区方式。
map端连接:连接在数据集到达map函数前就要执行,各map的输入数据须划分成等量分区并按连接键排序,同一键的所有记录均会放到同一分区中。利用CompositeInputFormat类来运行一个map端连接,其输入源和连接类型(内or外)可通过连接表达式配置。
reduce端连接:mapper为各个记录标记源(使用MultipleInputs),使用连接键作为map输出键,使键相同的记录放在同一个reducer中(记录间并未排序,可使用辅助排序对记录按不同源排序,使得当一个数据源数据到达时,另一个数据源数据已经在reducer中了)
4. 边数据分布
side data是作业所需额外只读数据,如何是所有map或reduce都能方便而高效使用边数据?
如果仅需要想任务传递少量元数据,秩序覆盖Mapper或Reducer类的configure()方法,并调用传入JonConf对象的getter方法即可。对于更复杂的对象需要自己处理序列化工作。
Hadoop的分布式缓存能够在任务运行过程中及时将文件和存档复制到任务结点以供使用,每个作业,个文件只需复制到一个结点一次。对于使用GenericOptionsParser的工具来说,用户可以使用-file选项指定待分发的文件,文件内包含以逗号隔开的URL列表。文件可以存放在本地文件系统、HDFS或其他Hadoop刻度文件系统之中。
%hadoop jar job.jar className -files cacheFile input output