Introducción
En la vasta extensión de un desierto árido, un solitario mercader emprende un peligroso viaje, buscando desentrañar los misterios escondidos debajo de las abrasadoras arenas. El objetivo del mercader es descubrir reliquias y artefactos antiguos, desbloqueando los secretos de una civilización olvidada hace mucho tiempo. Sin embargo, la gran cantidad de datos enterrados en el desierto plantea un formidable desafío, requiriendo el poder de Hadoop MapReduce para procesar y analizar efectivamente la información.
Implementando el Mapper
En este paso, crearemos una clase Mapper para procesar los datos crudos obtenidos de las excavaciones en el desierto. Nuestro objetivo es extraer la información relevante de los datos y prepararla para su análisis ulterior por el Reducer.
Utilice el comando su - hadoop para cambiar al usuario hadoop y automáticamente ir al directorio /home/hadoop. En este momento, use el comando ls. para ver el archivo de datos data*.txt. Luego cree y complete el archivo ArtifactMapper.java en ese directorio de acuerdo con el código siguiente:
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 {
// Divide la línea en palabras
String[] tokens = value.toString().split("\\s+");
// Emite cada palabra con un recuento de 1
for (String token : tokens) {
word.set(token);
context.write(word, ONE);
}
}
}
En la clase ArtifactMapper, extendemos la clase Mapper proporcionada por Hadoop. Se anula el método map para procesar cada par clave-valor de entrada.
- La clave de entrada es un
LongWritableque representa el desplazamiento de bytes de la línea de entrada, y el valor de entrada es un objetoTextque contiene la línea de texto del archivo de entrada. - El método
mapdivide la línea de entrada en palabras individuales utilizando el métodosplity la expresión regular"\\s+"para coincidir con uno o más caracteres de espacio en blanco. - Para cada palabra, el método
mapcrea un objetoTexty lo emite como clave, junto con un valorLongWritableconstante de1como valor, que representa el recuento de esa palabra.
Implementando el Reducer
En este paso, crearemos una clase Reducer para agregar los datos emitidos por el Mapper. El Reducer contará la frecuencia de cada palabra y producirá la salida final.
Cree y complete el archivo ArtifactReducer.java en el directorio /home/hadoop de acuerdo con el siguiente contenido de código:
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));
}
}
En la clase ArtifactReducer, extendemos la clase Reducer proporcionada por Hadoop. Se anula el método reduce para agregar los valores asociados con cada clave.
- La clave de entrada es un objeto
Textque representa la palabra, y los valores de entrada son unIterablede objetosLongWritableque representan los recuentos de esa palabra emitidos por los Mappers. - El método
reduceitera sobre los valores y calcula la suma de todos los recuentos para la palabra dada. - El método
reduceluego emite la palabra como clave y el recuento total como valor, utilizandocontext.write.
Creando el Driver
En este paso, crearemos una clase Controlador para coordinar el trabajo MapReduce. El Controlador configurará el trabajo, especificará las rutas de entrada y salida y enviará el trabajo al clúster de Hadoop.
Cree y complete el archivo ArtifactDriver.java en el directorio /home/hadoop de acuerdo con el siguiente contenido de código:
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");
// Especifique el archivo jar del trabajo por clase
job.setJarByClass(ArtifactDriver.class);
// Establezca las clases Mapper y Reducer
job.setMapperClass(ArtifactMapper.class);
job.setReducerClass(ArtifactReducer.class);
// Establezca los tipos de clave y valor de salida
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
// Establezca las rutas de entrada y salida
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// Envíe el trabajo y espere a que se complete
System.exit(job.waitForCompletion(true)? 0 : 1);
}
}
En la clase ArtifactDriver, creamos un trabajo MapReduce y lo configuramos para ejecutar nuestras clases ArtifactMapper y ArtifactReducer.
- El método
maincrea un nuevo objetoConfigurationy un objetoJobcon un nombre personalizado "Artifact Word Count". - Los métodos
setMapperClassysetReducerClassse utilizan para especificar las clases Mapper y Reducer que se utilizarán en el trabajo. - Los métodos
setOutputKeyClassysetOutputValueClassse utilizan para especificar los tipos de clave y valor de salida para el trabajo. - El método
FileInputFormat.addInputPathse utiliza para especificar la ruta de entrada para el trabajo, que se toma como el primer argumento de línea de comandos. - El método
FileOutputFormat.setOutputPathse utiliza para especificar la ruta de salida para el trabajo, que se toma como el segundo argumento de línea de comandos. - El método
job.waitForCompletionse llama para enviar el trabajo y esperar a que se complete. El programa sale con un código de estado de 0 si el trabajo es exitoso, o 1 si falla.
Compilando y Ejecutando el Trabajo
En este paso, compilaremos las clases Java y ejecutaremos el trabajo MapReduce en el clúster de Hadoop.
Primero, necesitamos compilar las clases 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
Este comando compila las clases Java y coloca los archivos .class compilados en el directorio actual. La opción -classpath incluye las rutas de la biblioteca de Hadoop, que se necesitan para compilar el código que utiliza clases de Hadoop. Los parámetros -source y -target se utilizan para especificar las versiones de código fuente y bytecode objetivo de Java para coincidir con la versión de Java en Hadoop
Luego, empaquetamos los archivos class con el comando jar:
jar -cvf Artifact.jar *.class
Finalmente, podemos ejecutar el trabajo MapReduce, y todos los datos sobre el desierto ya están almacenados en el directorio HDFS /input:
hadoop jar Artifact.jar ArtifactDriver /input /output
Después de ejecutar el comando, debería ver registros que indican el progreso del trabajo MapReduce. Una vez que el trabajo se complete, puede encontrar los archivos de salida en el directorio HDFS /output. Y use el siguiente comando para ver el resultado:
hdfs dfs -ls /output
hdfs dfs -cat /output/part-r-00000
Resumen
¡Felicidades! Has explorado con éxito el proceso de codificación de Mappers y Reducers para un trabajo MapReduce de Hadoop. Guiado por un escenario en el que un comerciante del desierto busca reliquias antiguas, has aprovechado el poder de Hadoop MapReduce para analizar grandes cantidades de datos del desierto. La implementación de la clase ArtifactMapper extrajo los datos relevantes, mientras que la clase ArtifactReducer agregó la salida del Mapper. La coordinación del proceso con la clase ArtifactDriver consolidó aún más tu comprensión. En todo momento, se puso énfasis en las mejores prácticas, ejemplos completos de código y verificaciones. Esta experiencia práctica profundizó tu comprensión de Hadoop MapReduce y destacó el diseño de una experiencia de aprendizaje efectiva.



