深入理解 Apache Hadoop MapReduce

作者:禅与计算机程序设计艺术

1.简介

Apache Hadoop MapReduce是一个开源的分布式计算框架,用于处理海量的数据集并在不限定集群大小或机器配置的情况下运行作业。其主要由两类组件构成:Map 阶段和 Reduce 阶段。 Map阶段负责对数据进行分片并将每个分片传递给不同的任务,它接收一个输入键值对,并生成零个或者多个输出键值对。Map阶段由一个Mapper函数实现,该函数将输入键值对映射到一系列的中间键值对。中间键值对存储在内存中。当所有的 Mapper 操作完成后,它将把结果写入磁盘文件系统中。 Reduce阶段负责从所有 Mapper 产生的中间键值对中汇总结果。它还负责按指定的排序方式对输出结果进行合并,并且可以设置不同的聚合器来控制最终输出结果的数量。Reduce 阶段由一个Reducer函数实现,该函数通过读取 Mapper 的输出文件并执行相同的键的聚合操作来构造最终结果。

通过将 Map 和 Reduce 操作解耦开,Hadoop MapReduce 可以允许用户自定义自己的功能。例如,用户可以通过编写各种自定义的 Mappers 或 Reducers 来解决特定类型的问题,也可以编写自己的 Combiner 函数来进行局部聚合,进一步提高性能。为了利用 Hadoop 的并行特性,Hadoop MapReduce 提供了以下三个主要特性:

基于磁盘的缓存:由于 Hadoop 是基于磁盘的系统,因此数据加载到内存时需要花费较长的时间。为了加快数据的处理速度,Hadoop MapReduce 使用了一种块存储机制,其中数据被划分成固定大小的块,并缓存在各个节点上。同时,Hadoop 会自动管理这些缓存,以确保它们足够可靠地服务于数据访问请求。 自动数据切分:Hadoop MapReduce 通过把数据分割成适合于单个节点的块的方式,自动地完成数据切分。用户无需考虑底层物理机的配置,也不需要担心网络带宽或磁盘 I/O 等因素影响应用程序的性能。 容错性:Hadoop MapReduce 使用了一系列的设计原则,包括副本机制、事务日志和检查点,确保系统的容错性。如果某个节点出现故障,它的任务会自动重启,而不会丢失任何状态信息。 基于 RPC 的远程过程调用(Remote Procedure Call)协议:Hadoop MapReduce 使用了一个基于 RPC 通信协议来构建集群的连接。此外,Hadoop MapReduce 提供了许多有用的命令行接口和图形界面,方便用户提交作业、监控作业执行情况等。 2.MapReduce概述 Hadoop MapReduce是一个用于分布式运算的编程模型和软件框架。它支持三个关键操作:map、shuffle and sort、reduce。用户只需指定输入、输出位置以及应用逻辑,即可利用MapReduce框架快速地处理大规模数据。

Map 阶段:Map 阶段通常由用户定义的 mapper 函数进行,它接受一组输入键值对并产生一组中间键值对。中间键值对存储在内存中,当所有 mapper 任务都完成之后,mapper 将产生的中间键值对输出到一个临时文件中。 Shuffle and Sort:shuffle and sort 过程负责对中间键值对进行排序、分组、重新分配,并且将中间键值对分配给相应的 reducer 进行处理。shuffle and sort 是一个有序过程,因此它具有良好的性能。 Reduce 阶段:Reduce 阶段由用户定义的 reducer 函数进行,它通过读取 mapper 产生的中间键值对文件,并执行相同的键的聚合操作,以便产生最终输出结果。

Hadoop 利用可伸缩性优势和容错机制保证了高可用性。Hadoop 集群能够自动检测硬件故障、网络问题和崩溃、系统错误等异常,并快速恢复,确保数据安全、准确、完整和一致。

下面我们逐一了解 Hadoops MapReduce 的一些基础概念和术语。

3.Hadoop MapReduce基本术语 Word Count 示例: 假设我们有如下文本数据样本:

apple banana cherry
dog cat elephant
fox grape hippopotamus
ice jupiter kangaroo
lemon mandarin orange
pear plum quince
raspberry sauce tomato
watermelon xenon yak
zebra zigzag zulu

现在,我们希望统计出每种水果出现的次数。最简单的办法可能就是利用 Word Count 模型。Word Count 模型表示的是对于每个词,我们统计出它在文本中出现的次数。比如,对于 "banana" 这个词,出现了一次,对于 "tomato" 这个词,又出现了一次,我们就认为其出现了两次。

Word Count 可以用 MapReduce 来实现。MapReduce 有两个阶段:Map 阶段和 Reduce 阶段。

Map 阶段:

1) 读取每个文档中的每一行作为输入; 2) 按照空格或制表符进行分割,提取每个单词并将其作为 key,其出现次数作为 value,写入中间文件(Intermediate File)。

<document-id> <word>   #中间文件
doc1 apple    1       #中间文件
doc1 banana   1       #中间文件
doc1 cherry   1       #中间文件
doc2 dog      1       #中间文件
......        ...      #中间文件

3) 对同一个 key 进行累计求和,并输出最终结果。

Reduce 阶段:

1) 从中间文件读取 key-value 对并将它们排序; 2) 根据相同 key 的 value 进行合并,将 key 和 value 的组合作为最终的结果输出。

apple    3
banana   1
cherry   1
dog      1
elephant 1
fox      1
grape    1
hippopotamus       1
ice     1
jupiter 1
kangaroo 1
lemon    1
mandarin 1
orange  1
pear    1
plum    1
quince  1
raspberry 1
sauce   1
tomato  2
watermelon 1
xenon   1
yak     1
zebra   1
zigzag  1
zulu    1

4) Hadoop Streaming API: 在实际开发中,用户可以自己编写 mapper 和 reducer 程序,然后运行 Hadoop 流处理程序(Streaming Program),它会根据用户提供的 jar 文件来启动 MapReduce 作业。Hadoop Streamin API 还提供了一些内置的功能来方便用户使用。例如,用户可以使用以下方法进行计数:

public static void main(String[] args) throws Exception {
    if (args.length!= 2) {
        System.err.println("Usage: wordcount <input> <output>");
        System.exit(-1);
    }

    Configuration conf = new Configuration();
    String inputPath = args[0];
    String outputPath = args[1];

    Job job = Job.getInstance(conf);
    job.setJarByClass(WordCount.class); // 此处填写用户提供的 jar 包名称
    job.setInputFormatClass(TextInputFormat.class);
    TextInputFormat.addInputPath(job, new Path(inputPath));

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);

    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);

    FileOutputFormat.setOutputPath(job, new Path(outputPath));

    boolean success = job.waitForCompletion(true);
    System.exit(success? 0 : 1);
}

猜你喜欢

转载自blog.csdn.net/universsky2015/article/details/133504798