En este tema, aprenderás a escribir un programa MapReduce desde cero. MapReduce es un modelo de programación que permite el procesamiento de grandes conjuntos de datos de manera distribuida. Este modelo se compone de dos fases principales: Map y Reduce.

Objetivos de Aprendizaje

  • Comprender la estructura básica de un programa MapReduce.
  • Escribir un programa MapReduce simple en Java.
  • Ejecutar y probar el programa en un entorno Hadoop.

Estructura de un Programa MapReduce

Un programa MapReduce típico consta de tres componentes principales:

  1. Mapper: Procesa los datos de entrada y genera pares clave-valor intermedios.
  2. Reducer: Procesa los pares clave-valor intermedios y genera los resultados finales.
  3. Driver: Configura y ejecuta el trabajo MapReduce.

  1. Mapper

El Mapper toma un conjunto de datos de entrada y los convierte en pares clave-valor intermedios. Aquí está la estructura básica de una clase Mapper en Java:

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

import java.io.IOException;

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

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String line = value.toString();
        String[] tokens = line.split("\\s+");
        for (String token : tokens) {
            word.set(token);
            context.write(word, one);
        }
    }
}

  1. Reducer

El Reducer toma los pares clave-valor intermedios generados por el Mapper y los procesa para generar los resultados finales.

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

import java.io.IOException;

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

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

  1. Driver

El Driver configura y ejecuta el trabajo MapReduce. Aquí se especifican las clases Mapper y Reducer, así como los formatos de entrada y salida.

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 WordCount {
    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(LongWritable.class);
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

Ejemplo Completo: Contador de Palabras

Vamos a combinar los tres componentes anteriores en un programa completo que cuenta la frecuencia de palabras en un conjunto de datos de texto.

Paso 1: Crear el Proyecto

  1. Crea un nuevo proyecto Java en tu IDE favorito.
  2. Añade las dependencias de Hadoop a tu proyecto.

Paso 2: Escribir el Código

Crea tres archivos Java: TokenizerMapper.java, IntSumReducer.java, y WordCount.java, y copia el código proporcionado anteriormente en cada archivo correspondiente.

Paso 3: Compilar y Empaquetar

Compila y empaqueta tu proyecto en un archivo JAR. Asegúrate de incluir todas las dependencias necesarias.

Paso 4: Ejecutar el Programa en Hadoop

  1. Sube el archivo JAR a tu clúster Hadoop.
  2. Ejecuta el trabajo MapReduce usando el siguiente comando:
hadoop jar WordCount.jar WordCount /ruta/de/entrada /ruta/de/salida

Ejercicio Práctico

Ejercicio: Modifica el programa de contador de palabras para que ignore las palabras comunes (stop words) como "the", "is", "in", etc.

Solución:

  1. Crea una lista de palabras comunes.
  2. Modifica el método map en TokenizerMapper para ignorar estas palabras.
import java.util.HashSet;
import java.util.Set;

public class TokenizerMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
    private final static LongWritable one = new LongWritable(1);
    private Text word = new Text();
    private Set<String> stopWords;

    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
        stopWords = new HashSet<>();
        stopWords.add("the");
        stopWords.add("is");
        stopWords.add("in");
        // Añade más palabras comunes según sea necesario
    }

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String line = value.toString();
        String[] tokens = line.split("\\s+");
        for (String token : tokens) {
            if (!stopWords.contains(token.toLowerCase())) {
                word.set(token);
                context.write(word, one);
            }
        }
    }
}

Conclusión

En esta sección, has aprendido a escribir un programa MapReduce básico en Java. Has visto cómo estructurar el código en Mapper, Reducer y Driver, y cómo ejecutar el programa en un entorno Hadoop. Además, has practicado modificando el programa para ignorar palabras comunes. En el siguiente módulo, profundizaremos en técnicas de optimización para mejorar el rendimiento de tus trabajos MapReduce.

© Copyright 2024. Todos los derechos reservados