Map Reduce est un cadre qui a été développé pour traiter efficacement des quantités massives de données. Par exemple, si nous avons 1 million d'enregistrements dans un ensemble de données, et qu'il est stocké dans une représentation relationnelle - il est très coûteux de dériver des valeurs et d'effectuer toute sorte de transformations sur celles-ci.
Par exemple, en SQL, compte tenu de la date de naissance, pour savoir combien de personnes sont âgées de> 30 ans pour un million d'enregistrements, cela prendrait du temps, et cela n'augmenterait que par ordre de magnitude lorsque la complexité de la requête augmente. Map Reduce fournit une implémentation basée sur un cluster où les données sont traitées de manière distribuée
Un autre bon exemple est Trouver des amis via la réduction de carte peut être un exemple puissant pour comprendre le concept et un cas d'utilisation bien utilisé.
Trouver des amis
MapReduce est un cadre développé à l'origine par Google qui permet un calcul distribué à grande échelle facile sur un certain nombre de domaines. Apache Hadoop est une implémentation open source.
Je vais passer en revue les détails, mais cela revient à définir deux fonctions: une fonction de carte et une fonction de réduction. La fonction de carte prend une valeur et génère des paires clé: valeur. Par exemple, si nous définissons une fonction de carte qui prend une chaîne et renvoie la longueur du mot comme clé et le mot lui-même comme valeur, alors map (steve) renverrait 5: steve et map (savannah) renverrait 8: savannah . Vous avez peut-être remarqué que la fonction de carte est sans état et ne nécessite que la valeur d'entrée pour calculer sa valeur de sortie. Cela nous permet d'exécuter la fonction de carte contre des valeurs en parallèle et offre un énorme avantage. Avant d'arriver à la fonction de réduction, le cadre mapreduce regroupe toutes les valeurs ensemble par clé, donc si les fonctions de mappage produisent la clé suivante: paires de valeurs:
3 : the
3 : and
3 : you
4 : then
4 : what
4 : when
5 : steve
5 : where
8 : savannah
8 : research
Ils sont regroupés en:
3 : [the, and, you]
4 : [then, what, when]
5 : [steve, where]
8 : [savannah, research]
Chacune de ces lignes serait ensuite passée comme argument à la fonction de réduction, qui accepte une clé et une liste de valeurs. Dans ce cas, nous pourrions essayer de comprendre combien de mots de certaines longueurs existent, donc notre fonction de réduction ne comptera que le nombre d'éléments dans la liste et affichera la clé avec la taille de la liste, comme:
3 : 3
4 : 3
5 : 2
8 : 2
Les réductions peuvent également être effectuées en parallèle, offrant à nouveau un énorme avantage. On peut alors regarder ces résultats finaux et voir qu'il n'y avait que deux mots de longueur 5 dans notre corpus, etc ...
L'exemple le plus courant de mapreduce consiste à compter le nombre de fois où des mots apparaissent dans un corpus. Supposons que vous ayez une copie d'Internet (j'ai eu la chance d'avoir travaillé dans une telle situation) et que vous vouliez une liste de chaque mot sur Internet ainsi que le nombre de fois où il s'est produit.
La façon dont vous aborderiez cela serait de symboliser les documents que vous avez (les diviser en mots) et de passer chaque mot à un mappeur. Le mappeur cracherait alors le mot avec une valeur de 1
. La phase de regroupement prendra toutes les clés (dans ce cas, les mots) et fera une liste de 1. La phase de réduction prend alors une clé (le mot) et une liste (une liste de 1 pour chaque fois que la clé est apparue sur Internet), et résume la liste. Le réducteur sort ensuite le mot, ainsi que son nombre. En fin de compte, vous aurez une liste de chaque mot sur Internet, ainsi que le nombre de fois qu'il est apparu.
Facile, non? Si vous avez déjà lu sur mapreduce, le scénario ci-dessus n'est pas nouveau ... c'est le "Hello, World" de mapreduce. Voici donc un cas d'utilisation réel (Facebook peut ou non faire ce qui suit, ce n'est qu'un exemple):
Facebook a une liste d'amis (notez que les amis sont une chose bidirectionnelle sur Facebook. Si je suis votre ami, vous êtes à moi). Ils ont également beaucoup d'espace disque et traitent des centaines de millions de demandes chaque jour. Ils ont décidé de pré-calculer les calculs quand ils le peuvent pour réduire le temps de traitement des demandes. Une demande de traitement courante est la fonctionnalité "Vous et Joe avez 230 amis en commun". Lorsque vous visitez le profil de quelqu'un, vous voyez une liste d'amis que vous avez en commun. Cette liste ne change pas fréquemment, il serait donc inutile de la recalculer à chaque fois que vous visitez le profil (bien sûr, vous pourriez utiliser une stratégie de mise en cache décente, mais je ne serais pas en mesure de continuer à écrire sur mapreduce pour ce problème). Nous allons utiliser mapreduce pour calculer tout le monde » s amis communs une fois par jour et enregistrer ces résultats. Plus tard, c'est juste une recherche rapide. Nous avons beaucoup de disque, c'est bon marché.
Supposons que les amis sont stockés en tant que Personne -> [Liste d'amis], notre liste d'amis est alors:
A -> B C D
B -> A C D E
C -> A B D E
D -> A B C E
E -> B C D
Chaque ligne sera un argument pour un mappeur. Pour chaque ami dans la liste d'amis, le mappeur affichera une paire clé-valeur. La clé sera un ami avec la personne. La valeur sera la liste d'amis. La clé sera triée de manière à ce que les amis soient en ordre, ce qui obligera toutes les paires d'amis à aller vers le même réducteur. C'est difficile à expliquer avec du texte, alors faisons-le et voyons si vous pouvez voir le motif. Une fois tous les mappeurs exécutés, vous aurez une liste comme celle-ci:
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)
Chaque ligne sera passée en argument à un réducteur. La fonction de réduction coupera simplement les listes de valeurs et produira la même clé avec le résultat de l'intersection. Par exemple, réduire ((AB) -> (ACDE) (BCD)) affichera (AB): (CD) et signifie que les amis A et B ont C et D comme amis communs.
Le résultat après réduction est:
(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)
Maintenant , quand le profil de visites D B, nous pouvons regarder rapidement (B D)
et de voir qu'ils ont trois amis en commun, (A C E)
.