魔法序列化精通

HadoopHadoopBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,你将学习如何为著名的魔法学院(Magical Academy)庞大的魔法典籍收藏优化编目流程。通过 Hadoop MapReduce 的强大功能,你将处理书籍数据的序列化,确保无缝的处理和分析。这将使你能够高效地存储和处理书籍信息,最终更好地服务于学院的教职员工和学生。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL hadoop(("`Hadoop`")) -.-> hadoop/HadoopMapReduceGroup(["`Hadoop MapReduce`"]) hadoop(("`Hadoop`")) -.-> hadoop/HadoopYARNGroup(["`Hadoop YARN`"]) hadoop(("`Hadoop`")) -.-> hadoop/HadoopHiveGroup(["`Hadoop Hive`"]) hadoop/HadoopMapReduceGroup -.-> hadoop/setup_jobs("`Setting up MapReduce Jobs`") hadoop/HadoopMapReduceGroup -.-> hadoop/mappers_reducers("`Coding Mappers and Reducers`") hadoop/HadoopMapReduceGroup -.-> hadoop/handle_serialization("`Handling Serialization`") hadoop/HadoopYARNGroup -.-> hadoop/yarn_jar("`Yarn Commands jar`") hadoop/HadoopHiveGroup -.-> hadoop/process("`Process Control Function`") hadoop/HadoopHiveGroup -.-> hadoop/udf("`User Defined Function`") subgraph Lab Skills hadoop/setup_jobs -.-> lab-288975{{"`魔法序列化精通`"}} hadoop/mappers_reducers -.-> lab-288975{{"`魔法序列化精通`"}} hadoop/handle_serialization -.-> lab-288975{{"`魔法序列化精通`"}} hadoop/yarn_jar -.-> lab-288975{{"`魔法序列化精通`"}} hadoop/process -.-> lab-288975{{"`魔法序列化精通`"}} hadoop/udf -.-> lab-288975{{"`魔法序列化精通`"}} end

实现 Writable 接口

在这一步中,我们将创建一个自定义的 Writable 类来表示书籍数据。该类将实现 Apache Hadoop 提供的 Writable 接口,以便在 MapReduce 过程中高效地进行数据的序列化和反序列化。

首先,你需要使用 su - hadoop 命令切换到 hadoop 用户,并在 /home/hadoop 目录下创建一个名为 Book.java 的 Java 文件,内容如下:

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.Writable;

// Book 类表示一本书,包含标题、作者和出版年份。
// 它实现了 Writable 接口以支持 Hadoop 的序列化。
public class Book implements Writable {
    // 书籍的标题、作者和出版年份的私有字段。
    private String title;
    private String author;
    private int year;

    // 默认构造函数 - 用于反序列化时创建新实例。
    public Book() {}

    // 带参数的构造函数,用于使用给定值初始化字段。
    public Book(String title, String author, int year) {
        this.title = title;
        this.author = author;
        this.year = year;
    }

    // write 方法将对象的字段序列化到 DataOutput。
    public void write(DataOutput out) throws IOException {
        out.writeUTF(title); // 将标题以 UTF-8 格式写入
        out.writeUTF(author); // 将作者以 UTF-8 格式写入
        out.writeInt(year); // 将出版年份以整数格式写入
    }

    // readFields 方法从 DataInput 反序列化对象的字段。
    public void readFields(DataInput in) throws IOException {
        title = in.readUTF(); // 以 UTF-8 格式读取标题
        author = in.readUTF(); // 以 UTF-8 格式读取作者
        year = in.readInt(); // 以整数格式读取出版年份
    }

    // toString 方法提供对象的字符串表示形式,
    // 这对于打印和日志记录非常有用。
    @Override
    public String toString() {
        return "Title: " + title + ", Author: " + author + ", Year: " + year;
    }

    // 为了简洁起见,省略了 getter 和 setter 方法,但它们是访问字段所必需的。
}

这个 Book 类包含书籍的标题、作者和出版年份字段。write 方法将书籍数据序列化为字节流,而 readFields 方法从字节流中反序列化数据。这两个方法都是 Writable 接口所必需的。

接下来,你需要使用以下命令编译 Java 类:

## 编译 Java 类
javac -source 8 -target 8 -classpath $HADOOP_HOME/share/hadoop/common/hadoop-common-3.3.6.jar:$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar:. Book.java

实现 Mapper 和 Reducer

在这一步中,我们将创建一个 Mapper 和一个 Reducer 类,使用 MapReduce 范式处理书籍数据。

自定义 BookMapper

首先,在 /home/hadoop 目录下创建一个名为 BookMapper.java 的 Java 文件,内容如下:

import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

// BookMapper 继承 Mapper 类以处理文本输入文件
// 输入的键值对为 LongWritable(行号)和 Text(行内容)
// 输出的键值对为 Text(作者名)和 Book(书籍详情)
public class BookMapper extends Mapper<LongWritable, Text, Text, Book> {
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // 按逗号分割输入行
        String[] bookData = value.toString().split(",");
        // 从输入行中提取标题、作者和年份
        String title = bookData[0];
        String author = bookData[1];
        int year = Integer.parseInt(bookData[2]);
        // 将作者和书籍详情写入上下文
        context.write(new Text(author), new Book(title, author, year));
    }
}

这个 BookMapper 类接收格式为 "title,author,year" 的输入数据行,并输出以作者为键、Book 对象为值的键值对。

自定义 BookReducer

接下来,在 /home/hadoop 目录下创建一个名为 BookReducer.java 的 Java 文件,内容如下:

import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

// BookReducer 继承 Reducer 类以按作者聚合书籍详情
// 输入的键值对为 Text(作者名)和 Book(书籍详情)
// 输出的键值对为 Text(作者名)和 Book(聚合后的书籍详情)
public class BookReducer extends Reducer<Text, Book, Text, Book> {
    @Override
    protected void reduce(Text key, Iterable<Book> values, Context context) throws IOException, InterruptedException {
        // 遍历同一作者的所有书籍,并将每本书写入上下文
        for (Book book : values) {
            context.write(key, book);
        }
    }
}

这个 BookReducer 类简单地将输入的键值对原样输出,实际上按作者对书籍进行了分组。

编译文件

最后,你需要使用以下命令编译 Java 类:

## 编译 Java 类
javac -source 8 -target 8 -classpath $HADOOP_HOME/share/hadoop/common/hadoop-common-3.3.6.jar:$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar:. BookMapper.java BookReducer.java

运行 MapReduce 任务

在这一步中,我们将创建一个 Driver 类来运行 MapReduce 任务并处理书籍数据。

自定义 BookDriver

首先,在 /home/hadoop 目录下创建一个名为 BookDriver.java 的 Java 文件,内容如下:

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

// BookDriver 用于设置并提交 MapReduce 任务
public class BookDriver {
    public static void main(String[] args) throws Exception {
        // 创建一个新的 Hadoop 任务配置
        Configuration conf = new Configuration();
        // 使用任务配置实例化一个 Job 对象
        Job job = Job.getInstance(conf, "Book Processing");
        // 通过类指定任务的 jar 文件
        job.setJarByClass(BookDriver.class);
        // 设置 Mapper 类
        job.setMapperClass(BookMapper.class);
        // 设置 Reducer 类
        job.setReducerClass(BookReducer.class);
        // 设置任务的输出键类
        job.setOutputKeyClass(Text.class);
        // 设置任务的输出值类
        job.setOutputValueClass(Book.class);
        // 设置任务的输入路径
        FileInputFormat.addInputPath(job, new Path(args[0]));
        // 设置任务的输出路径
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        // 根据任务完成状态退出
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

这个 BookDriver 类用于设置并运行 MapReduce 任务。它使用 BookMapperBookReducer 类配置任务,设置输入和输出路径,并等待任务完成。

执行任务

要运行 MapReduce 任务,你需要编译 Java 类并创建一个 JAR 文件。你可以使用以下命令:

## 编译 Java 类
javac -source 8 -target 8 -classpath $HADOOP_HOME/share/hadoop/common/hadoop-common-3.3.6.jar:$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar:. BookDriver.java

## 创建 JAR 文件
jar -cvf book.jar *.class

接下来,你需要创建一个输入目录并将一些示例书籍数据复制到其中。你可以使用以下命令:

## 创建输入目录
hdfs dfs -mkdir /input

## 将示例数据复制到输入目录
hdfs dfs -put ./data.txt /input

最后,你可以使用以下命令运行 MapReduce 任务:

hadoop jar book.jar BookDriver /input /output

该命令将运行 BookDriver 类,使用 /input 中的输入数据,并将结果输出到 /output。你可以使用以下命令查看结果:

hdfs dfs -cat /output/part-r-00000

总结

恭喜!你已经成功掌握了 Hadoop MapReduce 中的序列化技术,并完成了自定义 Writable 类的创建。通过魔法学院(Magical Academy)的图书管理员管理大量书籍的场景,你创建了一个实现 Writable 接口的 Book 类,以实现数据的无缝序列化和反序列化。你还编写了 BookMapper 类来提取书籍信息,以及 BookReducer 类来按作者高效地分组书籍,并通过 BookDriver 类协调整个流程。这包括编译 Java 类、创建 JAR 文件以及在 Hadoop 集群上执行任务等操作。在整个过程中,你积累了宝贵的 Hadoop MapReduce 经验,提升了在自定义 Writable 类、Mapper 和 Reducer 类以及协调大规模数据处理任务的 MapReduce 任务方面的技能。

您可能感兴趣的其他 Hadoop 教程