Hadoop Shuffle Combiner

HadoopBeginner
Pratique Agora

Introdução

Imagine um cenário onde você é um engenheiro talentoso encarregado de gerenciar dados em um sistema de simulação de batalha espacial. Seu objetivo é otimizar o desempenho do sistema implementando a técnica Hadoop Shuffle Combiner no processo MapReduce. Ao utilizar o Combiner, você visa reduzir o tráfego de rede e melhorar a eficiência geral no processamento de dados durante a simulação.

Escrever o Mapper

Nesta etapa, você escreverá a classe Mapper para processar os dados de entrada e emitir pares chave-valor intermediários.

Abra o terminal e siga as etapas abaixo para começar.

Mude o usuário para hadoop e, em seguida, mude para o diretório home do usuário hadoop:

su - hadoop

Crie um arquivo Java para a classe Mapper:

nano /home/hadoop/SpaceBattleMapper.java

Em seguida, adicione o seguinte código ao arquivo SpaceBattleMapper.java:

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

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

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // Split the input line into words
        String[] words = value.toString().split("\\s+");
        // Emit a key-value pair for each word
        for (String w : words) {
            word.set(w);
            context.write(word, one);
        }
    }
}

Dicas: Você pode copiar o código da caixa de prompt à direita e colá-lo com Ctrl + Shift + V no editor nano aberto. Pressione Ctrl + O para salvar o arquivo e Enter para confirmar quando solicitado pelo editor nano. Finalmente, use Ctrl + X para sair do editor.

A classe SpaceBattleMapper estende a classe Mapper do framework Hadoop. Ela é usada para processar dados de entrada na forma de pares chave-valor, onde a chave é um LongWritable representando o deslocamento em bytes da linha no arquivo de entrada, e o valor é um objeto Text representando a linha de texto.

A classe define dois campos privados:

  • one: Um objeto IntWritable com um valor constante de 1. Este é usado como o valor nos pares chave-valor emitidos.
  • word: Um objeto Text usado para armazenar cada palavra extraída da linha de entrada.

O método map é substituído para fornecer a lógica de mapeamento específica:

  • O valor Text de entrada é convertido em uma string e dividido em palavras com base em espaços em branco.
  • Para cada palavra no array, o objeto word é definido para essa palavra, e um par chave-valor é emitido com a palavra como a chave e one como o valor. Isso é feito usando o método context.write.

Esta classe Mapper foi projetada para emitir um par chave-valor para cada palavra nos dados de entrada, com a palavra como a chave e o inteiro 1 como o valor. Esta configuração é comumente usada em aplicações de contagem de palavras, onde o objetivo é contar as ocorrências de cada palavra em um conjunto de dados.

Implementar o Combiner

Nesta etapa, você implementará a classe Combiner para realizar a agregação local antes do embaralhamento (shuffling) dos dados.

Crie um arquivo Java para a classe Combiner:

nano /home/hadoop/SpaceBattleCombiner.java

Em seguida, adicione o seguinte código ao arquivo SpaceBattleCombiner.java:

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

public class SpaceBattleCombiner extends Reducer<Text, IntWritable, Text, IntWritable> {
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int sum = 0;
        // Sum up the values for each key
        for (IntWritable val : values) {
            sum += val.get();
        }
        // Emit the key and the sum of its values
        context.write(key, new IntWritable(sum));
    }
}

A classe SpaceBattleCombiner estende a classe Reducer do framework Hadoop. Ela é usada como um combiner no processo MapReduce para realizar a agregação local de pares chave-valor intermediários emitidos pelo Mapper.

A classe substitui o método reduce para fornecer a lógica específica do combiner:

  • O método recebe uma chave do tipo Text e um iterável de valores do tipo IntWritable como entrada. A chave representa uma palavra, e o iterável contém contagens de ocorrências dessa palavra.
  • O método itera sobre os valores, somando-os para obter a contagem total da palavra.
  • Finalmente, o método emite um par chave-valor com a palavra como a chave e a contagem total como o valor usando o método context.write.

O objetivo do SpaceBattleCombiner é realizar a agregação local das contagens para cada palavra antes que os dados sejam embaralhados (shuffled) pela rede para o Reducer. Isso reduz a quantidade de dados transferidos entre as fases Mapper e Reducer, melhorando a eficiência do trabalho MapReduce.

Implementar o Reducer

Nesta etapa, você implementará a classe Reducer para realizar a agregação final dos pares chave-valor.

  1. Crie um arquivo Java para a classe Reducer:
nano /home/hadoop/SpaceBattleReducer.java

Em seguida, adicione o seguinte código ao arquivo SpaceBattleReducer.java:

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

public class SpaceBattleReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int sum = 0;
        for (IntWritable val : values) {
            sum += val.get();
        }
        context.write(key, new IntWritable(sum));
    }
}

A classe SpaceBattleReducer estende a classe Reducer do framework Hadoop. Ela é usada para realizar a agregação final dos pares chave-valor intermediários emitidos pelo Mapper e, opcionalmente, processados pelo Combiner.

A classe substitui o método reduce para fornecer a lógica específica do reducer:

  • O método recebe uma chave do tipo Text e um iterável de valores do tipo IntWritable como entrada. A chave representa uma palavra, e o iterável contém contagens de ocorrências dessa palavra.
  • O método itera sobre os valores, somando-os para obter a contagem total da palavra.
  • Finalmente, o método emite um par chave-valor com a palavra como a chave e a contagem total como o valor usando o método context.write.

O SpaceBattleReducer realiza a agregação final dos dados, somando as contagens de cada palavra em todas as saídas do Mapper. Isso fornece a contagem final de ocorrências para cada palavra nos dados de entrada.

Escrever o Driver

Nesta etapa, você criará um arquivo Java para gerenciar o trabalho MapReduce, incluindo a configuração do trabalho e a especificação das classes Mapper, Combiner e Reducer.

Crie um arquivo Java para a classe Driver:

nano /home/hadoop/SpaceBattleDriver.java

Em seguida, adicione o seguinte código ao arquivo SpaceBattleDriver.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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class SpaceBattleDriver {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "Space Battle Simulation");
        job.setJarByClass(SpaceBattleDriver.class);
        job.setMapperClass(SpaceBattleMapper.class);
        job.setCombinerClass(SpaceBattleCombiner.class);
        job.setReducerClass(SpaceBattleReducer.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);
    }
}

A classe SpaceBattleDriver é responsável por configurar e executar o trabalho MapReduce para a simulação da batalha espacial.

  • A classe começa criando um novo objeto Configuration e uma instância Job com essa configuração. O trabalho recebe um nome, "Space Battle Simulation", para identificação.

  • O método setJarByClass é chamado com a classe SpaceBattleDriver para definir o arquivo jar que contém as classes necessárias para o trabalho.

  • Os métodos setMapperClass, setCombinerClass e setReducerClass são usados para especificar as classes que realizarão as tarefas de mapeamento, combinação e redução, respectivamente.

  • Os métodos setOutputKeyClass e setOutputValueClass definem os tipos da chave e do valor de saída, que são Text e IntWritable neste caso.

  • Os métodos FileInputFormat.addInputPath e FileOutputFormat.setOutputPath definem os caminhos para os dados de entrada e saída. Esses caminhos são passados como argumentos de linha de comando para o método main.

  • Finalmente, o método job.waitForCompletion é chamado para submeter o trabalho e aguardar sua conclusão. O método retorna true se o trabalho for concluído com sucesso e false caso contrário. O programa sai com um código de status de 0 se o trabalho for bem-sucedido e 1 se não for.

Esta classe driver une todos os componentes do trabalho MapReduce e é o ponto de entrada para a execução do trabalho.

Resumo

Neste laboratório, você percorreu a implementação da técnica Hadoop Shuffle Combiner em um cenário de simulação de batalha espacial. Ao seguir as etapas para criar as classes Mapper, Combiner, Reducer e Driver, você adquiriu experiência prática na otimização do processamento de dados em um ambiente Hadoop MapReduce. Este laboratório teve como objetivo aprimorar sua compreensão da redução da sobrecarga da rede e da melhoria da eficiência computacional em tarefas de processamento de big data.