MapReduce - Kombinierer

Ein Kombinierer, auch bekannt als semi-reducer, ist eine optionale Klasse, die die Eingaben aus der Map-Klasse akzeptiert und anschließend die Ausgabe-Schlüssel-Wert-Paare an die Reducer-Klasse übergibt.

Die Hauptfunktion eines Kombinierers besteht darin, die Kartenausgabedatensätze mit demselben Schlüssel zusammenzufassen. Die Ausgabe (Schlüsselwertsammlung) des Kombinierers wird als Eingabe über das Netzwerk an die eigentliche Reduziereraufgabe gesendet.

Kombinierer

Die Combiner-Klasse wird zwischen der Map-Klasse und der Reduce-Klasse verwendet, um das Datenübertragungsvolumen zwischen Map und Reduce zu reduzieren. Normalerweise ist die Ausgabe der Kartenaufgabe groß und die an die Reduzierungsaufgabe übertragenen Daten sind hoch.

Das folgende MapReduce-Aufgabendiagramm zeigt die COMBINER-PHASE.

Wie funktioniert Combiner?

Hier ist eine kurze Zusammenfassung der Funktionsweise von MapReduce Combiner -

  • Ein Kombinierer hat keine vordefinierte Schnittstelle und muss die redu () -Methode der Reducer-Schnittstelle implementieren.

  • Ein Kombinierer arbeitet mit jedem Kartenausgabeschlüssel. Es muss dieselben Ausgabeschlüsselwerttypen wie die Reducer-Klasse haben.

  • Ein Kombinierer kann zusammenfassende Informationen aus einem großen Datensatz erstellen, da er die ursprüngliche Kartenausgabe ersetzt.

Combiner ist zwar optional, hilft jedoch bei der Trennung von Daten in mehrere Gruppen für die Reduzierungsphase, wodurch die Verarbeitung vereinfacht wird.

MapReduce Combiner-Implementierung

Das folgende Beispiel bietet eine theoretische Vorstellung von Kombinierern. Nehmen wir an, wir haben die folgende Eingabetextdatei mit dem Nameninput.txt für MapReduce.

What do you mean by Object
What do you know about Java
What is Java Virtual Machine
How Java enabled High Performance

Die wichtigen Phasen des MapReduce-Programms mit Combiner werden unten erläutert.

Plattenleser

Dies ist die erste Phase von MapReduce, in der der Record Reader jede Zeile aus der Eingabetextdatei als Text liest und die Ausgabe als Schlüssel-Wert-Paare liefert.

Input - Zeile für Zeile Text aus der Eingabedatei.

Output- Bildet die Schlüssel-Wert-Paare. Das Folgende ist die Menge der erwarteten Schlüssel-Wert-Paare.

<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>

Kartenphase

Die Map-Phase nimmt Eingaben vom Record Reader entgegen, verarbeitet sie und erzeugt die Ausgabe als einen weiteren Satz von Schlüssel-Wert-Paaren.

Input - Das folgende Schlüssel-Wert-Paar ist die Eingabe aus dem 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>

Die Map-Phase liest jedes Schlüssel-Wert-Paar, trennt jedes Wort mit StringTokenizer vom Wert, behandelt jedes Wort als Schlüssel und die Anzahl dieses Wortes als Wert. Das folgende Codeausschnitt zeigt die Mapper-Klasse und die Map-Funktion.

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 - Die erwartete Ausgabe ist wie folgt -

<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>

Kombiniererphase

Die Combiner-Phase nimmt jedes Schlüssel-Wert-Paar aus der Map-Phase, verarbeitet es und erzeugt die Ausgabe als key-value collection Paare.

Input - Das folgende Schlüssel-Wert-Paar ist die Eingabe aus der Map-Phase.

<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>

Die Combiner-Phase liest jedes Schlüssel-Wert-Paar, kombiniert die gebräuchlichen Wörter als Schlüssel und die Werte als Sammlung. Normalerweise ähnelt der Code und die Funktionsweise eines Kombinierers dem eines Reduzierers. Im Folgenden finden Sie das Code-Snippet für die Mapper-, Combiner- und Reducer-Klassendeklaration.

job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);

Output - Die erwartete Ausgabe ist wie folgt -

<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>

Reduzierphase

Die Reduziererphase nimmt jedes Schlüsselwert-Erfassungspaar aus der Kombiniererphase, verarbeitet es und übergibt die Ausgabe als Schlüsselwertpaare. Beachten Sie, dass die Combiner-Funktionalität mit der des Reduzierers identisch ist.

Input - Das folgende Schlüssel-Wert-Paar ist die Eingabe aus der Combiner-Phase.

<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>

Die Reduziererphase liest jedes Schlüssel-Wert-Paar. Es folgt das Code-Snippet für den 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 - Die erwartete Leistung aus der Reduzierphase ist wie folgt: -

<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>

Plattenschreiber

Dies ist die letzte Phase von MapReduce, in der der Record Writer jedes Schlüssel-Wert-Paar aus der Reducer-Phase schreibt und die Ausgabe als Text sendet.

Input - Jedes Schlüssel-Wert-Paar aus der Reducer-Phase zusammen mit dem Ausgabeformat.

Output- Sie erhalten die Schlüssel-Wert-Paare im Textformat. Es folgt die erwartete Ausgabe.

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

Beispielprogramm

Der folgende Codeblock zählt die Anzahl der Wörter in einem Programm.

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);
   }
}

Speichern Sie das obige Programm als WordCount.java. Die Zusammenstellung und Ausführung des Programms ist unten angegeben.

Zusammenstellung und Ausführung

Nehmen wir an, wir befinden uns im Home-Verzeichnis des Hadoop-Benutzers (z. B. / home / hadoop).

Führen Sie die folgenden Schritte aus, um das obige Programm zu kompilieren und auszuführen.

Step 1 - Verwenden Sie den folgenden Befehl, um ein Verzeichnis zum Speichern der kompilierten Java-Klassen zu erstellen.

$ mkdir units

Step 2- Laden Sie Hadoop-core-1.2.1.jar herunter, mit dem das MapReduce-Programm kompiliert und ausgeführt wird. Sie können das Glas von mvnrepository.com herunterladen .

Nehmen wir an, der heruntergeladene Ordner ist / home / hadoop /.

Step 3 - Verwenden Sie die folgenden Befehle, um die zu kompilieren WordCount.java Programm und ein Glas für das Programm zu erstellen.

$ javac -classpath hadoop-core-1.2.1.jar -d units WordCount.java
$ jar -cvf units.jar -C units/ .

Step 4 - Verwenden Sie den folgenden Befehl, um ein Eingabeverzeichnis in HDFS zu erstellen.

$HADOOP_HOME/bin/hadoop fs -mkdir input_dir

Step 5 - Verwenden Sie den folgenden Befehl, um die benannte Eingabedatei zu kopieren input.txt im Eingabeverzeichnis von HDFS.

$HADOOP_HOME/bin/hadoop fs -put /home/hadoop/input.txt input_dir

Step 6 - Verwenden Sie den folgenden Befehl, um die Dateien im Eingabeverzeichnis zu überprüfen.

$HADOOP_HOME/bin/hadoop fs -ls input_dir/

Step 7 - Verwenden Sie den folgenden Befehl, um die Word-Zählanwendung auszuführen, indem Sie Eingabedateien aus dem Eingabeverzeichnis entnehmen.

$HADOOP_HOME/bin/hadoop jar units.jar hadoop.ProcessUnits input_dir output_dir

Warten Sie eine Weile, bis die Datei ausgeführt wird. Nach der Ausführung enthält die Ausgabe eine Reihe von Eingabeaufteilungen, Zuordnungsaufgaben und Reduzierungsaufgaben.

Step 8 - Verwenden Sie den folgenden Befehl, um die resultierenden Dateien im Ausgabeordner zu überprüfen.

$HADOOP_HOME/bin/hadoop fs -ls output_dir/

Step 9 - Verwenden Sie den folgenden Befehl, um die Ausgabe in anzuzeigen Part-00000Datei. Diese Datei wird von HDFS generiert.

$HADOOP_HOME/bin/hadoop fs -cat output_dir/part-00000

Es folgt die vom MapReduce-Programm generierte Ausgabe.

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