Los secretos místicos de la clasificación de Hadoop

HadoopHadoopBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En una misteriosa feria nocturna, una figura cautivadora adornada con una máscara ornamentada se mueve con gracia por la bulliciosa multitud. Esta bailarina de máscaras enigmática parece poseer un poder secreto, ordenando con facilidad los bulliciosos puestos en un arreglo ordenado con cada giro y movimiento. Tu objetivo es desentrañar el misterio detrás de este talento extraordinario mediante el dominio del arte de Hadoop Shuffle Comparable.


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/shuffle_partitioner("Shuffle Partitioner") hadoop/HadoopMapReduceGroup -.-> hadoop/shuffle_comparable("Shuffle Comparable") hadoop/HadoopMapReduceGroup -.-> hadoop/shuffle_combiner("Shuffle Combiner") 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-288996{{"Los secretos místicos de la clasificación de Hadoop"}} hadoop/mappers_reducers -.-> lab-288996{{"Los secretos místicos de la clasificación de Hadoop"}} hadoop/shuffle_partitioner -.-> lab-288996{{"Los secretos místicos de la clasificación de Hadoop"}} hadoop/shuffle_comparable -.-> lab-288996{{"Los secretos místicos de la clasificación de Hadoop"}} hadoop/shuffle_combiner -.-> lab-288996{{"Los secretos místicos de la clasificación de Hadoop"}} hadoop/yarn_jar -.-> lab-288996{{"Los secretos místicos de la clasificación de Hadoop"}} hadoop/process -.-> lab-288996{{"Los secretos místicos de la clasificación de Hadoop"}} hadoop/udf -.-> lab-288996{{"Los secretos místicos de la clasificación de Hadoop"}} end

Implementar el Mapper

En este paso, crearemos una clase Mapper personalizada para procesar los datos de entrada y emitir pares clave-valor. La clave será una clave compuesta que consta de dos campos: el primer carácter de cada palabra y la longitud de la palabra. El valor será la palabra misma.

Primero, cambie el usuario a hadoop y luego cambie al directorio home del usuario hadoop:

su - hadoop

Luego, cree un archivo Java para la clase Mapper:

touch /home/hadoop/WordLengthMapper.java

Agregue el siguiente código al archivo WordLengthMapper.java:

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

public class WordLengthMapper extends Mapper<LongWritable, Text, CompositeKey, Text> {

    private CompositeKey compositeKey = new CompositeKey();

    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String line = value.toString();
        String[] words = line.split("\\s+");

        for (String word : words) {
            compositeKey.setFirstChar(word.charAt(0));
            compositeKey.setLength(word.length());
            context.write(compositeKey, new Text(word));
        }
    }
}

En el código anterior, creamos una clase WordLengthMapper que extiende la clase Mapper de la API de MapReduce de Hadoop. El método map toma una clave LongWritable (que representa el desplazamiento en bytes de la línea de entrada) y un valor Text (la línea de entrada en sí). Luego divide la línea de entrada en palabras individuales, crea un objeto CompositeKey para cada palabra (que contiene el primer carácter y la longitud de la palabra) y emite la CompositeKey como clave y la palabra como valor.

Implementar la Clave Compuesta

En este paso, crearemos una clase CompositeKey personalizada que implemente la interfaz WritableComparable de la API de MapReduce de Hadoop. Esta clase se utilizará como la clave en nuestro trabajo de MapReduce, lo que nos permitirá ordenar y agrupar los datos según el primer carácter y la longitud de cada palabra.

Primero, cree un archivo Java para la clase CompositeKey:

touch /home/hadoop/CompositeKey.java

Luego, agregue el siguiente código al archivo CompositeKey.java:

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

public class CompositeKey implements WritableComparable<CompositeKey> {

    private char firstChar;
    private int length;

    public CompositeKey() {
    }

    public void setFirstChar(char firstChar) {
        this.firstChar = firstChar;
    }

    public char getFirstChar() {
        return firstChar;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int getLength() {
        return length;
    }

    @Override
    public void write(DataOutput out) throws IOException {
        out.writeChar(firstChar);
        out.writeInt(length);
    }

    @Override
    public void readFields(DataInput in) throws IOException {
        firstChar = in.readChar();
        length = in.readInt();
    }

    @Override
    public int compareTo(CompositeKey other) {
        int cmp = Character.compare(firstChar, other.firstChar);
        if (cmp!= 0) {
            return cmp;
        }
        return Integer.compare(length, other.length);
    }

    @Override
    public int hashCode() {
        return firstChar + length;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof CompositeKey) {
            CompositeKey other = (CompositeKey) obj;
            return firstChar == other.firstChar && length == other.length;
        }
        return false;
    }

    @Override
    public String toString() {
        return firstChar + ":" + length;
    }
}

En el código anterior, creamos una clase CompositeKey que implementa la interfaz WritableComparable. Tiene dos campos: firstChar (el primer carácter de una palabra) y length (la longitud de la palabra). La clase proporciona métodos getter y setter para estos campos, así como implementaciones de los métodos write, readFields, compareTo, hashCode, equals y toString requeridos por la interfaz WritableComparable.

El método compareTo es particularmente importante, ya que define cómo se ordenarán las claves en el trabajo de MapReduce. En nuestra implementación, primero comparamos los campos firstChar de las dos claves. Si son diferentes, devolvemos el resultado de esa comparación. Si los campos firstChar son iguales, entonces comparamos los campos length.

Implementar el Reductor

En este paso, crearemos una clase Reductor personalizada para procesar los pares clave-valor emitidos por el Mapper y generar la salida final.

Primero, cree un archivo Java para la clase Reductor:

touch /home/hadoop/WordLengthReducer.java

Luego, agregue el siguiente código al archivo WordLengthReducer.java:

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

public class WordLengthReducer extends Reducer<CompositeKey, Text, CompositeKey, Text> {

    public void reduce(CompositeKey key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
        StringBuilder sb = new StringBuilder();
        for (Text value : values) {
            sb.append(value.toString()).append(", ");
        }
        sb.setLength(sb.length() - 2);
        context.write(key, new Text(sb.toString()));
    }
}

En el código anterior, creamos una clase WordLengthReducer que extiende la clase Reducer de la API de MapReduce de Hadoop. El método reduce toma una clave CompositeKey (que contiene el primer carácter y la longitud de una palabra) y un Iterable de valores Text (las palabras que coinciden con la clave).

Dentro del método reduce, concatenamos todas las palabras que coinciden con la clave en una cadena separada por comas. Utilizamos un StringBuilder para construir eficientemente la cadena de salida, y eliminamos la coma y el espacio finales antes de escribir el par clave-valor en la salida.

Implementar el Controlador

En este paso, crearemos una clase Controlador para configurar y ejecutar el trabajo de MapReduce.

Primero, cree un archivo Java para la clase Controlador:

touch /home/hadoop/WordLengthDriver.java

Luego, agregue el siguiente código al archivo WordLengthDriver.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;

public class WordLengthDriver {

    public static void main(String[] args) throws Exception {
        if (args.length!= 2) {
            System.err.println("Uso: WordLengthDriver <entrada> <salida>");
            System.exit(1);
        }

        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "Longitud de Palabras");

        job.setJarByClass(WordLengthDriver.class);
        job.setMapperClass(WordLengthMapper.class);
        job.setReducerClass(WordLengthReducer.class);
        job.setOutputKeyClass(CompositeKey.class);
        job.setOutputValueClass(Text.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        System.exit(job.waitForCompletion(true)? 0 : 1);
    }
}

En el código anterior, creamos una clase WordLengthDriver que sirve como punto de entrada para nuestro trabajo de MapReduce. El método main toma dos argumentos de línea de comandos: la ruta de entrada y la ruta de salida para el trabajo.

Dentro del método main, creamos un nuevo objeto Configuration y un nuevo objeto Job. Configuramos el trabajo estableciendo las clases del mapper y del reducer, las clases de la clave de salida y del valor de salida, y las rutas de entrada y salida.

Finalmente, enviamos el trabajo y esperamos a que se complete. Si el trabajo se completa correctamente, salimos con un código de estado de 0; de lo contrario, salimos con un código de estado de 1.

Para ejecutar el trabajo, puede usar el siguiente comando:

javac -source 8 -target 8 -classpath "/home/hadoop/:/home/hadoop/hadoop/share/hadoop/common/hadoop-common-3.3.6.jar:/home/hadoop/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar:/home/hadoop/hadoop/share/hadoop/common/lib/*" -d /home/hadoop /home/hadoop/WordLengthMapper.java /home/hadoop/CompositeKey.java /home/hadoop/WordLengthReducer.java /home/hadoop/WordLengthDriver.java
jar cvf word-length.jar *.class
hadoop jar word-length.jar WordLengthDriver /input /output

Finalmente, podemos comprobar los resultados ejecutando el siguiente comando:

hadoop fs -cat /output/*

Salida de ejemplo:

A:3 Amr
A:6 AADzCv
A:10 AlGyQumgIl
...
h:7 hgQUIhA
h:8 hyrjMGbY, hSElGKux
h:10 hmfHJjCkwB
...
z:6 zkpRCN
z:8 zfMHRbtk
z:9 zXyUuLHma

Resumen

En este laboratorio, exploramos el concepto de Hadoop Shuffle Comparable al implementar un trabajo de MapReduce que agrupa palabras según su primer carácter y longitud. Creamos un Mapper personalizado para emitir pares clave-valor con una clave compuesta, una clase CompositeKey personalizada que implementa la interfaz WritableComparable, un Reductor para concatenar palabras con la misma clave y una clase Driver para configurar y ejecutar el trabajo.

A través de este laboratorio, adquirí una comprensión más profunda del marco de MapReduce de Hadoop y de la importancia de los tipos de datos personalizados y la clasificación en el cálculo distribuido. Al dominar Hadoop Shuffle Comparable, podemos diseñar algoritmos eficientes para el procesamiento y análisis de datos, desbloqueando el poder de los datos masivos como el enigmático bailarín de máscara que ordena los puestos del mercado nocturno caótico.