Поиск в данных пустыни

HadoopHadoopBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В огромном пустыне-dessерте один торговец отправляется в опасный путь, пытаясь разгадать тайны, скрытые под жёстким солнцем и песком. Целью торговца является обнаружение древних реликвий и артефактов, раскрытие секретов давно забытой цивилизации. Однако огромный объем данных, заложенных в песке, представляет собой огромную проблему, требующую мощности Hadoop MapReduce для эффективной обработки и анализа информации.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL hadoop(("Hadoop")) -.-> hadoop/HadoopHiveGroup(["Hadoop Hive"]) hadoop(("Hadoop")) -.-> hadoop/HadoopMapReduceGroup(["Hadoop MapReduce"]) hadoop(("Hadoop")) -.-> hadoop/HadoopYARNGroup(["Hadoop YARN"]) hadoop/HadoopMapReduceGroup -.-> hadoop/setup_jobs("Setting up MapReduce Jobs") hadoop/HadoopMapReduceGroup -.-> hadoop/mappers_reducers("Coding Mappers and Reducers") hadoop/HadoopYARNGroup -.-> hadoop/yarn_jar("Yarn Commands jar") hadoop/HadoopHiveGroup -.-> hadoop/process("Process Control Function") hadoop/HadoopHiveGroup -.-> hadoop/aggregating("Aggregating Function") hadoop/HadoopHiveGroup -.-> hadoop/udf("User Defined Function") subgraph Lab Skills hadoop/setup_jobs -.-> lab-288986{{"Поиск в данных пустыни"}} hadoop/mappers_reducers -.-> lab-288986{{"Поиск в данных пустыни"}} hadoop/yarn_jar -.-> lab-288986{{"Поиск в данных пустыни"}} hadoop/process -.-> lab-288986{{"Поиск в данных пустыни"}} hadoop/aggregating -.-> lab-288986{{"Поиск в данных пустыни"}} hadoop/udf -.-> lab-288986{{"Поиск в данных пустыни"}} end

Реализация маппера

В этом шаге мы создадим класс маппера для обработки сырых данных, полученных из раскопок в пустыне. Наша цель - извлечь из данных соответствующую информацию и подготовить ее для дальнейшего анализа редьюсером.

Используйте команду su - hadoop, чтобы переключиться на пользователя hadoop и автоматически перейти в директорию /home/hadoop. В этот момент используйте команду ls., чтобы увидеть файл данных data*.txt. Затем создайте и заполните файл ArtifactMapper.java в этой директории в соответствии с кодом ниже:

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

public class ArtifactMapper extends Mapper<LongWritable, Text, Text, LongWritable> {

    private final static LongWritable ONE = new LongWritable(1);
    private Text word = new Text();

    @Override
    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // Разделяем строку на слова
        String[] tokens = value.toString().split("\\s+");

        // Выводим каждое слово с количеством 1
        for (String token : tokens) {
            word.set(token);
            context.write(word, ONE);
        }
    }
}

В классе ArtifactMapper мы расширяем класс Mapper, предоставляемый Hadoop. Метод map переопределяется для обработки каждой пары ключ-значение входных данных.

  1. Входной ключ - это LongWritable, представляющий смещение байтов в строке входных данных, а входное значение - это объект Text, содержащий строку текста из входного файла.
  2. Метод map разделяет входную строку на отдельные слова с использованием метода split и регулярного выражения "\\s+" для сопоставления одного или более пробельных символов.
  3. Для каждого слова метод map создает объект Text и выводит его в качестве ключа, а также постоянное значение LongWritable равное 1 в качестве значения, представляющее количество этого слова.

Реализация редьюсера

В этом шаге мы создадим класс редьюсера для агрегации данных, выданных маппером. Редьюсер подсчитает количество вхождений каждого слова и выдаст окончательный результат.

Создайте и заполните файл ArtifactReducer.java в директории /home/hadoop в соответствии с следующим содержанием кода:

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

public class ArtifactReducer extends Reducer<Text, LongWritable, Text, LongWritable> {

    @Override
    public void reduce(Text key, Iterable<LongWritable> values, Context context)
            throws IOException, InterruptedException {
        long sum = 0;
        for (LongWritable value : values) {
            sum += value.get();
        }
        context.write(key, new LongWritable(sum));
    }
}

В классе ArtifactReducer мы расширяем класс Reducer, предоставляемый Hadoop. Метод reduce переопределяется для агрегации значений, связанных с каждым ключом.

  1. Входной ключ - это объект Text, представляющий слово, а входные значения - это Iterable объектов LongWritable, представляющих количество вхождений этого слова, выданных мапперами.
  2. Метод reduce перебирает значения и вычисляет сумму всех подсчетов для данного слова.
  3. Затем метод reduce выводит слово в качестве ключа и общую сумму в качестве значения, используя context.write.

Создание драйвера

В этом шаге мы создадим класс драйвера для управления процессом MapReduce. Драйвер настроит задачу, укажет пути для ввода и вывода и отправит задачу в кластер Hadoop.

Создайте и заполните файл ArtifactDriver.java в директории /home/hadoop в соответствии с следующим содержанием кода:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
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;

public class ArtifactDriver {

    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "Artifact Word Count");

        // Укажите jar-файл задачи по классу
        job.setJarByClass(ArtifactDriver.class);

        // Установите классы маппера и редьюсера
        job.setMapperClass(ArtifactMapper.class);
        job.setReducerClass(ArtifactReducer.class);

        // Установите типы ключей и значений вывода
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        // Установите пути для ввода и вывода
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        // Отправьте задачу и подождите ее завершения
        System.exit(job.waitForCompletion(true)? 0 : 1);
    }
}

В классе ArtifactDriver мы создаем задачу MapReduce и настраиваем ее для запуска наших классов ArtifactMapper и ArtifactReducer.

  1. Метод main создает новый объект Configuration и объект Job с именем "Artifact Word Count".
  2. Методы setMapperClass и setReducerClass используются для указания классов маппера и редьюсера, которые будут использоваться в задаче.
  3. Методы setOutputKeyClass и setOutputValueClass используются для указания типов ключей и значений вывода для задачи.
  4. Метод FileInputFormat.addInputPath используется для указания пути для ввода задачи, который берется в качестве первого аргумента командной строки.
  5. Метод FileOutputFormat.setOutputPath используется для указания пути для вывода задачи, который берется в качестве второго аргумента командной строки.
  6. Метод job.waitForCompletion вызывается для отправки задачи и ожидания ее завершения. Программа завершается с кодом статуса 0, если задача выполнена успешно, или 1, если она завершилась с ошибкой.

Компиляция и запуск задачи

В этом шаге мы скомпилируем Java-классы и запустим задачу MapReduce на кластере Hadoop.

Во - первых, нам нужно скомпилировать 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:. *.java

Эта команда компилирует Java-классы и помещает скомпилированные файлы .class в текущую директорию. Параметр -classpath включает пути к библиотекам Hadoop, которые необходимы для компиляции кода, использующего классы Hadoop. Параметры -source и -target используются для указания версий исходного Java и целевого байт-кода, чтобы соответствовать версии Java в Hadoop.

Далее, упакуем файлы .class с помощью команды jar:

jar -cvf Artifact.jar *.class

Наконец, мы можем запустить задачу MapReduce, и все данные о пустыне уже хранятся в директории HDFS /input:

hadoop jar Artifact.jar ArtifactDriver /input /output

После выполнения команды вы должны увидеть логи, показывающие прогресс задачи MapReduce. Как только задача завершена, вы можете найти выходные файлы в директории HDFS /output. И используйте следующие команды, чтобы просмотреть результат:

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

Резюме

Поздравляем! Вы успешно освоили процесс написания кодов мапперов и редьюсеров для задачи Hadoop MapReduce. Руководствуясь сценарием, в котором торговец в пустыне ищет древние артефакты, вы воспользовались мощью Hadoop MapReduce для анализа огромных данных о пустыне. Реализация класса ArtifactMapper позволяла извлекать соответствующие данные, а класс ArtifactReducer агрегировал выходные данные маппера. Управление процессом с использованием класса ArtifactDriver еще более углубило ваше понимание. На протяжении всего процесса акцентировалось внимание на лучших практиках, полных примерах кода и проверках. Этот практический опыт углубил ваше понимание Hadoop MapReduce и подчеркнул эффективный дизайн обучения.