Введение
В этом лабораторном задании вы научитесь упростить процесс каталогизации огромного собрания магических томов в знаменитой Магческой Академии. С помощью Hadoop MapReduce вы будете обрабатывать сериализацию данных о книгах, обеспечивая бесперебойную обработку и анализ. Это позволит вам эффективно хранить и обрабатывать информацию о книгах, в конечном итоге лучше обслуживать преподавателей и студентов академии.
Реализация интерфейса Writable
В этом шаге мы создадим пользовательский класс Writable для представления данных о книгах. Этот класс реализует интерфейс Writable, предоставляемый Apache Hadoop, что позволяет эффективно сериализовать и десериализовать данные в процессе MapReduce.
Во - первых, вам нужно использовать команду su - hadoop, чтобы стать пользователем hadoop, и создать новый Java - файл с именем Book.java в директории /home/hadoop со следующим содержимым:
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;
}
// Геттеры и сеттеры опущены для краткости, но необходимы для доступа к полям.
}
В этом классе 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.
Custom BookMapper
Во - первых, создайте новый Java - файл с именем BookMapper.java в директории /home/hadoop со следующим содержимым:
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 в качестве значения.
Custom BookReducer
Далее, создайте новый Java - файл с именем BookReducer.java в директории /home/hadoop со следующим содержимым:
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 - задачу и обработать данные о книгах.
Custom BookDriver
Во - первых, создайте новый Java - файл с именем BookDriver.java в директории /home/hadoop со следующим содержимым:
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 - задачу. Он настраивает задачу с использованием классов BookMapper и BookReducer, задает входной и выходной пути и ожидает завершения задачи.
Выполнение задачи
Для запуска 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. В рамках сценария, где Старший библиотекарь Магческой Академии управляет огромным сборником книг, вы создали класс Book, реализующий интерфейс Writable для бесперебойной сериализации и десериализации данных. Создав класс BookMapper для извлечения информации о книгах и класс BookReducer для эффективной группировки книг по автору, вы организовали процесс с использованием класса BookDriver. Это включало задачи, такие как компиляция Java - классов, создание JAR - файла и выполнение задачи на кластере Hadoop. Весьма ценным навыком, который вы приобрели, является опыт работы с Hadoop MapReduce, а также умение создавать пользовательские классы Writable, классы Mapper и Reducer, а также организовывать MapReduce - задачи для обработки больших объемов данных.



