MapReduce 详解

FileInputFormat 实现类

TextInputFormat

TextInputFormat 是默认的 FileInputFormat 实现类。按行读取每条记录。 键是 LongWritable 类型,存储该行在整个文件中的起始字节偏移量。值是 Text 类型,存储这行的内容,不包括任何行终止符(换行符和回车符)。

KeyValueTextInputFormat

每一行均为一条记录,被分隔符分割为 key,value 。可以通过在驱动类中进行以下设置
来设定分隔符。默认分隔符是 tab(\t)。

1
conf.set(KeyValueLineRecordReader.KEY_VALUE_SEPERATOR, "\t");

NLineInputFormat

如果使用 NlineInputFormat,代表每个 map 进程处理的 InputSplit 不再按 block 块去划分,而是按 NlineInputFormat 指定的行数 N 来划分。 即输入文件的总行数/N=切片数, 如果不整除, 切片数=商+1。这里的键和值与 TextInputFormat 生成的一样。

使用该类,需要在驱动类中进行以下设置:

1
2
job.setInputFormatClass(NLineInputFormat.class)
NLineInputFormat.setNumLinesPerSplit(job, 3); // N=3

自定义 InputFormat

在企业开发中,Hadoop 框架自带的 InputFormat 类型不能够满足所有应用场景,需要自定义 InputFormat 来解决实际问题。

自定义 InputFormat 步骤如下:

  1. 自定义一个类继承 FileInputFormat。
    • 重写 isSplitable() 方法,返回 false 不可切割
    • 重写 createRecordReader() ,创建自定义的 RecordReader 对象,并初始化。
  2. 改写 RecordReader,实现一次读取一个完整文件封装为 KV。
    • 采用 IO 流一次读取一个文件输出到 value 中,因为设置了不可切片,最终把所有的文件都封装到了 value 中
    • 获取文件路径信息 + 名称,并设置 key
  3. 在输出时使用 SequenceFileOutPutFormat 输出合并文件。

    • 设置输入的 InputFormat

      1
      job.setInputFormatClass(WholeFileInputFormat.class);
    • 设置输出的 OutputFormat

      1
      job.setOutputFormatClass(SequenceFileOutputFormat.class);

Partition 分区

自定义分区

自定义 Partitioner 步骤

  1. 自定义类继承 Partitioner, 重写 getPartition() 方法

    1
    2


  2. 在 job 驱动中,设置自定义 partitioner

    1
    job.setPartitionerClass(CustomPartitioner.class);
  3. 自定义 partition 后,要根据自定义 partitioner 的逻辑设置相应数量的 reduce task

    1
    job.setNumReduceTasks(5);

排序

部分排序

MapReduce 根据输入记录的键对数据集排序。 保证输出的每个文件内部排序。

全排序

最终输出结果只有一个文件,且文件内部有序。实现方式是只设置一个 ReduceTask 但该方法在处理大型文件时效率极低,因为一台机器必须处理所有输出文件,从而完全丧失了
MapReduce 所提供的并行架构。

辅助排序

在 Reduce 端对 key 进行分组。应用于,在接收的 key 为 bean 对象时,想让一个或几个字段相同的 key 进入到同一个 reduce 方法时,可以采用分组排序。

Mapreduce 框架在记录到达 reducer 之前按键对记录排序,但键所对应的值并没有被排序。甚至在不同的执行轮次中,这些值的排序也不固定,因为它们来自不同的 map 任务且这些 map 任务在不同轮次中完成时间各不相同。一般来说,大多数 MapReduce 程序会避免让 reduce 函数依赖于值的排序。但是,有时也需要通过特定的方法对键进行排序和分组等以实现对值的排序。

自定义排序 WritableComparable

bean 对象做为 key 传输,需要实现 WritableComparable 接口重写 compareTo 方法, 就可以实现排序

OutputFormat 数据输出

OutputFormat 是 MapReduce 输出的基类,所有实现 MapReduce 输出都实现了 OutputFormat 接口。下面我们介绍几种常见的 OutputFormat 实现类。

OutputFormat 接口实现类

  1. 文本输出 TextOutputFormat
    默认的输出格式是 TextOutputFormat,它把每条记录写为文本行。它的键和值可以是任意类型,因为 TextOutputFormat 调用 toString() 方法把它们转换为字符串。
  2. SequenceFileOutputFormat
    SequenceFileOutputFormat 将它的输出写为一个顺序文件。如果输出需要作为后续 MapReduce 任务的输入,这便是一种好的输出格式,因为它的格式紧凑,很容易被压缩。
  3. 自定义 OutputFormat
    根据用户需求,自定义实现输出。
坚持原创技术分享,您的支持将鼓励我继续创作!