Geheimnisse der magischen Hadoop-Sortierung

HadoopHadoopBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In einem mysteriösen Nachtmarkt bewegt sich eine fesselnde Figur, gekleidet in eine prachtvolle Maske, graziös durch die geschäftige Menge. Dieser rätselhafte Maskentänzer scheint ein Geheimnis zu besitzen und sortiert mit jeder Drehung und Bewegung die chaotischen Stände mühelos in eine geordnete Anordnung. Dein Ziel ist es, das Geheimnis hinter diesem bemerkenswerten Talent zu entwirren, indem du die Kunst des Hadoop Shuffle Comparable beherrschst.


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{{"Geheimnisse der magischen Hadoop-Sortierung"}} hadoop/mappers_reducers -.-> lab-288996{{"Geheimnisse der magischen Hadoop-Sortierung"}} hadoop/shuffle_partitioner -.-> lab-288996{{"Geheimnisse der magischen Hadoop-Sortierung"}} hadoop/shuffle_comparable -.-> lab-288996{{"Geheimnisse der magischen Hadoop-Sortierung"}} hadoop/shuffle_combiner -.-> lab-288996{{"Geheimnisse der magischen Hadoop-Sortierung"}} hadoop/yarn_jar -.-> lab-288996{{"Geheimnisse der magischen Hadoop-Sortierung"}} hadoop/process -.-> lab-288996{{"Geheimnisse der magischen Hadoop-Sortierung"}} hadoop/udf -.-> lab-288996{{"Geheimnisse der magischen Hadoop-Sortierung"}} end

Implementiere den Mapper

In diesem Schritt erstellen wir eine benutzerdefinierte Mapper-Klasse, um die Eingabedaten zu verarbeiten und Schlüssel-Wert-Paare auszugeben. Der Schlüssel wird ein zusammengesetzter Schlüssel sein, der aus zwei Feldern besteht: das erste Zeichen jedes Wortes und die Länge des Wortes. Der Wert wird das Wort selbst sein.

Ändern Sie zunächst den Benutzer in hadoop und wechseln Sie dann in das Home-Verzeichnis des hadoop-Benutzers:

su - hadoop

Erstellen Sie dann eine Java-Datei für die Mapper-Klasse:

touch /home/hadoop/WordLengthMapper.java

Fügen Sie den folgenden Code zur WordLengthMapper.java-Datei hinzu:

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

Im obigen Code erstellen wir eine WordLengthMapper-Klasse, die von der Mapper-Klasse der Hadoop MapReduce-API erbt. Die map-Methode erhält einen LongWritable-Schlüssel (der die Byte-Offset der Eingabezeile repräsentiert) und einen Text-Wert (die Eingabezeile selbst). Sie teilt dann die Eingabezeile in einzelne Wörter auf, erstellt für jedes Wort ein CompositeKey-Objekt (enthaltend das erste Zeichen und die Länge des Wortes) und gibt das CompositeKey als Schlüssel und das Wort als Wert aus.

Implementiere den zusammengesetzten Schlüssel

In diesem Schritt erstellen wir eine benutzerdefinierte CompositeKey-Klasse, die das WritableComparable-Interface der Hadoop MapReduce-API implementiert. Diese Klasse wird als Schlüssel in unserem MapReduce-Job verwendet, was uns ermöglicht, die Daten basierend auf dem ersten Zeichen und der Länge jedes Wortes zu sortieren und zu gruppieren.

Erstellen Sie zunächst eine Java-Datei für die CompositeKey-Klasse:

touch /home/hadoop/CompositeKey.java

Fügen Sie dann den folgenden Code zur CompositeKey.java-Datei hinzu:

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

Im obigen Code erstellen wir eine CompositeKey-Klasse, die das WritableComparable-Interface implementiert. Sie hat zwei Felder: firstChar (das erste Zeichen eines Wortes) und length (die Länge des Wortes). Die Klasse bietet Getter- und Setter-Methoden für diese Felder sowie Implementierungen der write, readFields, compareTo, hashCode, equals und toString-Methoden, die vom WritableComparable-Interface erforderlich sind.

Die compareTo-Methode ist besonders wichtig, da sie definiert, wie die Schlüssel im MapReduce-Job sortiert werden. In unserer Implementierung vergleichen wir zunächst die firstChar-Felder der beiden Schlüssel. Wenn sie unterschiedlich sind, geben wir das Ergebnis dieser Vergleichs zurück. Wenn die firstChar-Felder gleich sind, vergleichen wir dann die length-Felder.

Implementiere den Reduzierer

In diesem Schritt erstellen wir eine benutzerdefinierte Reduzierer-Klasse, um die Schlüssel-Wert-Paare zu verarbeiten, die vom Mapper ausgegeben werden, und das endgültige Ergebnis zu generieren.

Erstellen Sie zunächst eine Java-Datei für die Reduzierer-Klasse:

touch /home/hadoop/WordLengthReducer.java

Fügen Sie dann den folgenden Code zur WordLengthReducer.java-Datei hinzu:

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

Im obigen Code erstellen wir eine WordLengthReducer-Klasse, die von der Reducer-Klasse der Hadoop MapReduce-API erbt. Die reduce-Methode erhält einen CompositeKey-Schlüssel (der das erste Zeichen und die Länge eines Wortes enthält) und ein Iterable von Text-Werten (die Wörter, die dem Schlüssel entsprechen).

Innerhalb der reduce-Methode verbinden wir alle Wörter, die dem Schlüssel entsprechen, zu einem komma-getrennten String. Wir verwenden einen StringBuilder, um effizient die Ausgabestring zu erstellen, und entfernen das abschließende Komma und Leerzeichen, bevor wir das Schlüssel-Wert-Paar in die Ausgabe schreiben.

Implementiere den Treiber

In diesem Schritt erstellen wir eine Treiber-Klasse, um die MapReduce-Aufgabe zu konfigurieren und auszuführen.

Erstellen Sie zunächst eine Java-Datei für die Treiber-Klasse:

touch /home/hadoop/WordLengthDriver.java

Fügen Sie dann den folgenden Code zur WordLengthDriver.java-Datei hinzu:

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("Usage: WordLengthDriver <input> <output>");
            System.exit(1);
        }

        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf, "Word Length");

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

Im obigen Code erstellen wir eine WordLengthDriver-Klasse, die als Einstiegspunkt für unsere MapReduce-Aufgabe dient. Die main-Methode nimmt zwei Befehlszeilenargumente entgegen: den Eingabepfad und den Ausgabepfad für die Aufgabe.

Innerhalb der main-Methode erstellen wir ein neues Configuration-Objekt und ein neues Job-Objekt. Wir konfigurieren die Aufgabe, indem wir die Mapper- und Reducer-Klassen, die Ausgabeschlüssel- und -wertklassen sowie die Eingabe- und Ausgabepfade festlegen.

Schließlich übermitteln wir die Aufgabe und warten auf ihre Fertigstellung. Wenn die Aufgabe erfolgreich abgeschlossen ist, beenden wir mit einem Statuscode von 0; andernfalls beenden wir mit einem Statuscode von 1.

Um die Aufgabe auszuführen, können Sie den folgenden Befehl verwenden:

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

Schließlich können wir die Ergebnisse überprüfen, indem wir folgenden Befehl ausführen:

hadoop fs -cat /output/*

Beispielausgabe:

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

Zusammenfassung

In diesem Lab haben wir das Konzept von Hadoop Shuffle Comparable erkundet, indem wir eine MapReduce-Aufgabe implementiert haben, die Wörter basierend auf ihrem ersten Zeichen und ihrer Länge gruppiert. Wir haben eine benutzerdefinierte Mapper erstellt, um Schlüssel-Wert-Paare mit einem zusammengesetzten Schlüssel auszugeben, eine benutzerdefinierte CompositeKey-Klasse, die das WritableComparable-Interface implementiert, einen Reducer, um Wörter mit demselben Schlüssel zusammenzufügen, und eine Driver-Klasse, um die Aufgabe zu konfigurieren und auszuführen.

Durch dieses Lab habe ich ein tieferes Verständnis des Hadoop MapReduce-Frameworks und der Wichtigkeit benutzerdefinierter Datentypen und Sortierung in der verteilten Computierung gewonnen. Indem wir Hadoop Shuffle Comparable beherrschen, können wir effiziente Algorithmen für die Datenverarbeitung und -analyse entwerfen und die Macht von Big Data entfalten, ähnlich wie der rätselhafte Maskentänzer, der die chaotischen Nachtmarktstände sortiert.