使用 Docker 启动单机 Hadoop 本地模式

Hadoop 是一个开源的框架,主要用于处理大规模数据集。它通过分布式计算来实现高速的数据处理。Hadoop 的核心组件包括 HDFS(Hadoop Distributed File System)和 MapReduce。虽然 Hadoop 的强大之处体现在它的分布式计算能力上,但在进行开发和测试时,使用单机模式(尤其是本地模式)会更加高效。本文将介绍如何使用 Docker 启动一个单机 Hadoop,并在本地模式下运行 MapReduce 任务。

1. 环境准备

在进行 Docker 实现之前,请确保你的机器上已安装 Docker。可以通过运行以下命令来检查是否正确安装:

docker --version

如果未安装,请按照 [Docker 官方文档]( 中的步骤进行安装。

2. 拉取 Hadoop Docker 镜像

在 Docker Hub 上有许多 Hadoop 的镜像可用,这里我们选择一个常用的镜像。

docker pull sequenceiq/hadoop-docker:2.7.1

3. 启动 Docker 容器

接下来,我们将通过以下命令启动 Hadoop 容器:

docker run -it sequenceiq/hadoop-docker:2.7.1 /etc/bootstrap.sh -bash

该命令会使用 sequenceiq/hadoop-docker:2.7.1 镜像启动一个交互式的容器,并执行启动脚本。

4. Hadoop 配置

在容器启动后,可以通过以下命令检查 Hadoop 的版本:

hadoop version

现在我们需要配置 Hadoop 的运行模式为本地模式。在 Hadoop 的配置目录中(通常是 /etc/hadoop/conf),打开 core-site.xml 文件。使用以下命令进入该目录:

cd /etc/hadoop/conf

在该目录下,使用编辑器(如 nanovim)编辑 core-site.xml 文件:

<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>file:///</value>
    </property>
</configuration>

添加以上内容后,保存并退出。

接下来,我们将配置 mapred-site.xml 文件,使其支持本地模式。在同一目录下打开该文件:

<configuration>
    <property>
        <name>mapreduce.framework.name</name>
        <value>local</value>
    </property>
</configuration>

同样,保存并退出。

5. 创建简单的 MapReduce 程序

接下来,我们将创建一个简单的 MapReduce 程序。以下是一个示例 Java 代码,用于统计文本文件中每个单词出现的次数。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class WordCount {

    public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {
        private final static IntWritable one = new IntWritable(1);
        private Text word = new Text();

        public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            String[] words = value.toString().split("\\s+");
            for (String w : words) {
                word.set(w);
                context.write(word, one);
            }
        }
    }

    public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
        private IntWritable result = new IntWritable();

        public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            int sum = 0;
            for (IntWritable val : values) {
                sum += val.get();
            }
            result.set(sum);
            context.write(key, result);
        }
    }

    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "word count");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(TokenizerMapper.class);
        job.setCombinerClass(IntSumReducer.class);
        job.setReducerClass(IntSumReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

将上述代码保存为 WordCount.java 文件。

6. 编译并运行程序

首先,我们需要编译 Java 程序。确保已经安装了 JDK 和 Hadoop 的相关依赖。可以使用以下命令进行编译和打包:

javac -classpath $(hadoop classpath) -d . WordCount.java
jar -cvf wordcount.jar .

编译完成后,使用以下命令运行 MapReduce 程序:

hadoop jar wordcount.jar WordCount <input_path> <output_path>

其中 <input_path> 是输入文件的路径,<output_path> 是输出结果的路径。

7. 类图与序列图

在上述程序中,涉及多个类(Mapper、Reducer 和主程序)。使用 Mermaid 语法绘制类图如下:

classDiagram
    class WordCount {
        + main(args: String[])
    }
    class TokenizerMapper {
        + map(key: Object, value: Text, context: Context)
    }
    class IntSumReducer {
        + reduce(key: Text, values: Iterable<IntWritable>, context: Context)
    }
    
    WordCount --> TokenizerMapper
    WordCount --> IntSumReducer

以下是程序执行过程的序列图:

sequenceDiagram
    participant User
    participant WordCount
    participant Mapper
    participant Reducer

    User->>WordCount: start execution
    WordCount->>Mapper: map(input data)
    Mapper->>Reducer: output intermediate data
    Reducer->>WordCount: return final result
    WordCount->>User: display output

结尾

通过本文的介绍,我们成功地在本地模式下使用 Docker 启动了一个 Hadoop 环境,并运行了一个简单的 WordCount MapReduce 程序。虽然本地模式的特点是占用单个节点的资源,但它对于开发和测试非常有效。希望通过这个实例,你能够更加深入理解 Hadoop 的工作原理,并在实际项目中加以应用。如果你对大数据处理有更高的需求,不妨尝试 Hadoop 的分布式模式,去体验它更强大的能力。