MapReduce - Combinadores
Un combinador, también conocido como semi-reducer, es una clase opcional que opera aceptando las entradas de la clase Map y luego pasando los pares clave-valor de salida a la clase Reducer.
La función principal de un combinador es resumir los registros de salida del mapa con la misma clave. La salida (colección de valores-clave) del combinador se enviará a través de la red a la tarea Reducer real como entrada.
Combinador
La clase Combiner se usa entre la clase Map y la clase Reduce para reducir el volumen de transferencia de datos entre Map y Reduce. Por lo general, la salida de la tarea de mapa es grande y los datos transferidos a la tarea de reducción son altos.
El siguiente diagrama de tareas de MapReduce muestra la FASE COMBINADOR.
¿Cómo funciona Combiner?
Aquí hay un breve resumen sobre cómo funciona MapReduce Combiner:
Un combinador no tiene una interfaz predefinida y debe implementar el método reduce () de la interfaz Reducer.
Un combinador opera en cada tecla de salida del mapa. Debe tener los mismos tipos de clave-valor de salida que la clase Reducer.
Un combinador puede producir información resumida a partir de un conjunto de datos grande porque reemplaza la salida del mapa original.
Aunque Combiner es opcional, ayuda a segregar datos en varios grupos para la fase Reducir, lo que facilita su procesamiento.
Implementación de MapReduce Combiner
El siguiente ejemplo proporciona una idea teórica sobre los combinadores. Supongamos que tenemos el siguiente archivo de texto de entrada llamadoinput.txt para MapReduce.
What do you mean by Object
What do you know about Java
What is Java Virtual Machine
How Java enabled High Performance
Las fases importantes del programa MapReduce con Combiner se analizan a continuación.
Lector de registros
Esta es la primera fase de MapReduce donde el lector de registros lee cada línea del archivo de texto de entrada como texto y produce la salida como pares clave-valor.
Input - Texto línea a línea del archivo de entrada.
Output- Forma los pares clave-valor. El siguiente es el conjunto de pares clave-valor esperados.
<1, What do you mean by Object>
<2, What do you know about Java>
<3, What is Java Virtual Machine>
<4, How Java enabled High Performance>
Fase de mapa
La fase de mapa toma la entrada del lector de registros, la procesa y produce la salida como otro conjunto de pares clave-valor.
Input - El siguiente par clave-valor es la entrada tomada del Record Reader.
<1, What do you mean by Object>
<2, What do you know about Java>
<3, What is Java Virtual Machine>
<4, How Java enabled High Performance>
La fase de mapa lee cada par clave-valor, divide cada palabra del valor usando StringTokenizer, trata cada palabra como clave y el recuento de esa palabra como valor. El siguiente fragmento de código muestra la clase Mapper y la función map.
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>
{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context) throws IOException, InterruptedException
{
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens())
{
word.set(itr.nextToken());
context.write(word, one);
}
}
}
Output - La salida esperada es la siguiente -
<What,1> <do,1> <you,1> <mean,1> <by,1> <Object,1>
<What,1> <do,1> <you,1> <know,1> <about,1> <Java,1>
<What,1> <is,1> <Java,1> <Virtual,1> <Machine,1>
<How,1> <Java,1> <enabled,1> <High,1> <Performance,1>
Fase combinador
La fase de combinación toma cada par clave-valor de la fase de mapa, lo procesa y produce la salida como key-value collection pares.
Input - El siguiente par clave-valor es la entrada tomada de la fase Mapa.
<What,1> <do,1> <you,1> <mean,1> <by,1> <Object,1>
<What,1> <do,1> <you,1> <know,1> <about,1> <Java,1>
<What,1> <is,1> <Java,1> <Virtual,1> <Machine,1>
<How,1> <Java,1> <enabled,1> <High,1> <Performance,1>
La fase de combinación lee cada par clave-valor, combina las palabras comunes como clave y los valores como colección. Por lo general, el código y el funcionamiento de un Combinador son similares a los de un Reductor. A continuación se muestra el fragmento de código para la declaración de clases Mapper, Combiner y Reducer.
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
Output - La salida esperada es la siguiente -
<What,1,1,1> <do,1,1> <you,1,1> <mean,1> <by,1> <Object,1>
<know,1> <about,1> <Java,1,1,1>
<is,1> <Virtual,1> <Machine,1>
<How,1> <enabled,1> <High,1> <Performance,1>
Fase reductora
La fase Reducer toma cada par de colección clave-valor de la fase Combiner, lo procesa y pasa la salida como pares clave-valor. Tenga en cuenta que la funcionalidad del Combinador es la misma que la del Reductor.
Input - El siguiente par clave-valor es la entrada tomada de la fase Combiner.
<What,1,1,1> <do,1,1> <you,1,1> <mean,1> <by,1> <Object,1>
<know,1> <about,1> <Java,1,1,1>
<is,1> <Virtual,1> <Machine,1>
<How,1> <enabled,1> <High,1> <Performance,1>
La fase Reductor lee cada par clave-valor. A continuación se muestra el fragmento de código del Combiner.
public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable>
{
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException
{
int sum = 0;
for (IntWritable val : values)
{
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
Output - La salida esperada de la fase Reductor es la siguiente -
<What,3> <do,2> <you,2> <mean,1> <by,1> <Object,1>
<know,1> <about,1> <Java,3>
<is,1> <Virtual,1> <Machine,1>
<How,1> <enabled,1> <High,1> <Performance,1>
Escritor de discos
Esta es la última fase de MapReduce donde Record Writer escribe cada par clave-valor de la fase Reducer y envía la salida como texto.
Input - Cada par clave-valor de la fase Reductor junto con el formato de salida.
Output- Le da los pares clave-valor en formato de texto. A continuación se muestra el resultado esperado.
What 3
do 2
you 2
mean 1
by 1
Object 1
know 1
about 1
Java 3
is 1
Virtual 1
Machine 1
How 1
enabled 1
High 1
Performance 1
Programa de ejemplo
El siguiente bloque de código cuenta el número de palabras de un programa.
import java.io.IOException;
import java.util.StringTokenizer;
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.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class WordCount {
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>
{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context) throws IOException, InterruptedException
{
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens())
{
word.set(itr.nextToken());
context.write(word, one);
}
}
}
public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable>
{
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException
{
int sum = 0;
for (IntWritable val : values)
{
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
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(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
Guarde el programa anterior como WordCount.java. A continuación se detalla la compilación y ejecución del programa.
Compilación y ejecución
Supongamos que estamos en el directorio de inicio del usuario de Hadoop (por ejemplo, / home / hadoop).
Siga los pasos que se indican a continuación para compilar y ejecutar el programa anterior.
Step 1 - Utilice el siguiente comando para crear un directorio para almacenar las clases de Java compiladas.
$ mkdir units
Step 2- Descarga Hadoop-core-1.2.1.jar, que se utiliza para compilar y ejecutar el programa MapReduce. Puede descargar el archivo jar desde mvnrepository.com .
Supongamos que la carpeta descargada es / home / hadoop /.
Step 3 - Utilice los siguientes comandos para compilar WordCount.java programa y para crear un frasco para el programa.
$ javac -classpath hadoop-core-1.2.1.jar -d units WordCount.java
$ jar -cvf units.jar -C units/ .
Step 4 - Utilice el siguiente comando para crear un directorio de entrada en HDFS.
$HADOOP_HOME/bin/hadoop fs -mkdir input_dir
Step 5 - Utilice el siguiente comando para copiar el archivo de entrada llamado input.txt en el directorio de entrada de HDFS.
$HADOOP_HOME/bin/hadoop fs -put /home/hadoop/input.txt input_dir
Step 6 - Utilice el siguiente comando para verificar los archivos en el directorio de entrada.
$HADOOP_HOME/bin/hadoop fs -ls input_dir/
Step 7 - Utilice el siguiente comando para ejecutar la aplicación de conteo de palabras tomando archivos de entrada del directorio de entrada.
$HADOOP_HOME/bin/hadoop jar units.jar hadoop.ProcessUnits input_dir output_dir
Espere un momento hasta que se ejecute el archivo. Después de la ejecución, la salida contiene una serie de divisiones de entrada, tareas de mapa y tareas de reducción.
Step 8 - Utilice el siguiente comando para verificar los archivos resultantes en la carpeta de salida.
$HADOOP_HOME/bin/hadoop fs -ls output_dir/
Step 9 - Utilice el siguiente comando para ver la salida en Part-00000archivo. Este archivo es generado por HDFS.
$HADOOP_HOME/bin/hadoop fs -cat output_dir/part-00000
A continuación se muestra la salida generada por el programa MapReduce.
What 3
do 2
you 2
mean 1
by 1
Object 1
know 1
about 1
Java 3
is 1
Virtual 1
Machine 1
How 1
enabled 1
High 1
Performance 1