Map Reduce ist ein Framework, das entwickelt wurde, um große Datenmengen effizient zu verarbeiten. Wenn beispielsweise ein Datensatz 1 Million Datensätze enthält und dieser in einer relationalen Darstellung gespeichert ist, ist es sehr teuer, Werte abzuleiten und Transformationen für diese durchzuführen.
Zum Beispiel würde es in SQL unter Berücksichtigung des Geburtsdatums eine Weile dauern, um herauszufinden, wie viele Personen für eine Million Datensätze> 30 Jahre alt sind, und dies würde nur in der Größenordnung der Größe zunehmen, wenn die Komplexität der Abfrage zunimmt. Map Reduce bietet eine clusterbasierte Implementierung, bei der Daten verteilt verarbeitet werden
Ein weiteres gutes Beispiel ist das Finden von Freunden über Kartenreduzierung. Dies kann ein aussagekräftiges Beispiel für das Verständnis des Konzepts und ein häufig verwendeter Anwendungsfall sein.
Freunde finden
MapReduce ist ein ursprünglich bei Google entwickeltes Framework, das einfaches verteiltes Computing in großem Maßstab über eine Reihe von Domänen hinweg ermöglicht. Apache Hadoop ist eine Open Source-Implementierung.
Ich werde die Details beschönigen, aber es kommt darauf an, zwei Funktionen zu definieren: eine Kartenfunktion und eine Reduzierungsfunktion. Die Map-Funktion nimmt einen Wert an und gibt Schlüssel-Wert-Paare aus. Wenn wir beispielsweise eine Kartenfunktion definieren, die eine Zeichenfolge verwendet und die Länge des Wortes als Schlüssel und das Wort selbst als Wert ausgibt, gibt map (steve) 5: steve und map (savannah) 8: savannah zurück . Möglicherweise haben Sie bemerkt, dass die Kartenfunktion zustandslos ist und nur den Eingabewert benötigt, um den Ausgabewert zu berechnen. Dies ermöglicht es uns, die Kartenfunktion für Werte parallel auszuführen und bietet einen großen Vorteil. Bevor wir zur Reduktionsfunktion kommen, gruppiert das Mapreduce-Framework alle Werte nach Schlüsseln. Wenn die Kartenfunktionen also den folgenden Schlüssel ausgeben: Wertepaare:
3 : the
3 : and
3 : you
4 : then
4 : what
4 : when
5 : steve
5 : where
8 : savannah
8 : research
Sie werden gruppiert als:
3 : [the, and, you]
4 : [then, what, when]
5 : [steve, where]
8 : [savannah, research]
Jede dieser Zeilen würde dann als Argument an die Reduktionsfunktion übergeben, die einen Schlüssel und eine Liste von Werten akzeptiert. In diesem Fall versuchen wir möglicherweise herauszufinden, wie viele Wörter bestimmter Länge vorhanden sind. Unsere Reduzierungsfunktion zählt also nur die Anzahl der Elemente in der Liste und gibt den Schlüssel mit der Größe der Liste aus, z.
3 : 3
4 : 3
5 : 2
8 : 2
Die Reduzierungen können auch parallel durchgeführt werden, was wiederum einen großen Vorteil darstellt. Wir können uns dann diese Endergebnisse ansehen und feststellen, dass unser Korpus nur zwei Wörter der Länge 5 usw. enthielt.
Das häufigste Beispiel für Mapreduce ist das Zählen der Häufigkeit, mit der Wörter in einem Korpus vorkommen. Angenommen, Sie hatten eine Kopie des Internets (ich hatte das Glück, in einer solchen Situation gearbeitet zu haben), und Sie wollten eine Liste aller Wörter im Internet sowie die Häufigkeit, mit der sie vorkamen.
Die Art und Weise, wie Sie dies angehen würden, besteht darin, die vorhandenen Dokumente zu token (in Wörter aufzuteilen) und jedes Wort an einen Mapper zu übergeben. Der Mapper würde dann das Wort zusammen mit einem Wert von wieder ausspucken1
. In der Gruppierungsphase werden alle Schlüssel (in diesem Fall Wörter) verwendet und eine Liste mit Einsen erstellt. Die Reduzierungsphase nimmt dann einen Schlüssel (das Wort) und eine Liste (eine Liste von Einsen für jedes Mal, wenn der Schlüssel im Internet erscheint) und summiert die Liste. Der Reduzierer gibt dann das Wort zusammen mit seiner Anzahl aus. Wenn alles gesagt und getan ist, haben Sie eine Liste aller Wörter im Internet, zusammen mit der Häufigkeit, mit der sie erschienen sind.
Einfach richtig? Wenn Sie jemals über Mapreduce gelesen haben, ist das obige Szenario nichts Neues ... es ist die "Hallo Welt von Mapreduce". Hier ist also ein realer Anwendungsfall (Facebook kann Folgendes tun oder auch nicht, es ist nur ein Beispiel):
Facebook hat eine Liste von Freunden (beachte, dass Freunde auf Facebook eine bidirektionale Sache sind. Wenn ich dein Freund bin, gehörst du mir). Sie haben auch viel Speicherplatz und bedienen täglich Hunderte Millionen Anfragen. Sie haben beschlossen, Berechnungen vorab zu berechnen, wenn dies möglich ist, um die Verarbeitungszeit von Anforderungen zu verkürzen. Eine häufige Verarbeitungsanforderung ist die Funktion "Sie und Joe haben 230 Freunde gemeinsam". Wenn Sie das Profil einer Person besuchen, wird eine Liste mit Freunden angezeigt, die Sie gemeinsam haben. Diese Liste ändert sich nicht häufig, daher wäre es verschwenderisch, sie jedes Mal neu zu berechnen, wenn Sie das Profil besuchen (sicher, Sie könnten eine anständige Caching-Strategie verwenden, aber dann könnte ich nicht weiter über Mapreduce für dieses Problem schreiben). Wir werden mapreduce verwenden, damit wir alle berechnen können. ' s gemeinsame Freunde einmal am Tag und speichern Sie diese Ergebnisse. Später ist es nur eine kurze Suche. Wir haben viel Festplatte, es ist billig.
Angenommen, die Freunde werden als Person -> [Liste der Freunde] gespeichert. Unsere Freundesliste lautet dann:
A -> B C D
B -> A C D E
C -> A B D E
D -> A B C E
E -> B C D
Jede Zeile ist ein Argument für einen Mapper. Für jeden Freund in der Freundesliste gibt der Mapper ein Schlüssel-Wert-Paar aus. Der Schlüssel wird ein Freund zusammen mit der Person sein. Der Wert ist die Liste der Freunde. Der Schlüssel wird so sortiert, dass die Freunde in Ordnung sind, sodass alle Freundepaare zum selben Reduzierer gehen. Dies ist mit Text schwer zu erklären. Lassen Sie es uns einfach tun und sehen, ob Sie das Muster sehen können. Nachdem alle Mapper ausgeführt wurden, wird eine Liste wie die folgende angezeigt:
For map(A -> B C D) :
(A B) -> B C D
(A C) -> B C D
(A D) -> B C D
For map(B -> A C D E) : (Note that A comes before B in the key)
(A B) -> A C D E
(B C) -> A C D E
(B D) -> A C D E
(B E) -> A C D E
For map(C -> A B D E) :
(A C) -> A B D E
(B C) -> A B D E
(C D) -> A B D E
(C E) -> A B D E
For map(D -> A B C E) :
(A D) -> A B C E
(B D) -> A B C E
(C D) -> A B C E
(D E) -> A B C E
And finally for map(E -> B C D):
(B E) -> B C D
(C E) -> B C D
(D E) -> B C D
Before we send these key-value pairs to the reducers, we group them by their keys and get:
(A B) -> (A C D E) (B C D)
(A C) -> (A B D E) (B C D)
(A D) -> (A B C E) (B C D)
(B C) -> (A B D E) (A C D E)
(B D) -> (A B C E) (A C D E)
(B E) -> (A C D E) (B C D)
(C D) -> (A B C E) (A B D E)
(C E) -> (A B D E) (B C D)
(D E) -> (A B C E) (B C D)
Jede Zeile wird als Argument an einen Reduzierer übergeben. Die Reduzierungsfunktion schneidet einfach die Wertelisten und gibt denselben Schlüssel mit dem Ergebnis der Schnittmenge aus. Beispiel: Reduzieren ((AB) -> (ACDE) (BCD)) gibt (AB): (CD) aus und bedeutet, dass Freunde A und B C und D als gemeinsame Freunde haben.
Das Ergebnis nach der Reduktion ist:
(A B) -> (C D)
(A C) -> (B D)
(A D) -> (B C)
(B C) -> (A D E)
(B D) -> (A C E)
(B E) -> (C D)
(C D) -> (A B E)
(C E) -> (B D)
(D E) -> (B C)
Wenn D jetzt Bs Profil besucht, können wir schnell nachsehen, (B D)
dass sie drei gemeinsame Freunde haben (A C E)
.