• Aucun résultat trouvé

La distribution du patron de conception MapReduce permet de traiter de grands volumes de

données [Dean & Ghemawat 2008]. Dans ce modèle, deux fonctions empruntées à la program-

mation fonctionnelle sont utilisées. La fonction map filtre les données en entrée du système pour en extraire les informations utiles. La fonction reduce agrège et traite les données préalablement filtrées afin de créer les résultats. Ainsi, les jobs MapReduce sont divisés en deux ensembles de tâches, les tâches map et les tâches reduce, qui sont distribuées sur plusieurs nœuds de calcul (par exemple une grappe de PCs). Ces deux fonctions, fournies par l’utilisateur pour le traitement

spécifique de ses données, possèdent les signatures suivantes1 :

map : (K1, V1) → [(K2, V2)]

reduce : (K2, [V2]) → [(K3, V3)]

Parmi les nœuds de calculs, ceux qui exécutent la fonction de map sont appelés les mappers et

ceux qui exécutent la fonction de reduce les reducers. La figure3.1illustre le flux de données et

de contrôle dans un système distribué qui applique MapReduce :

1. le superviseur affecte les différents fragments des données d’entrée aux mappers ;

2. les mappers appliquent la fonction map sur les données d’entrée et créent les couples

intermédiaires clé-valeur de type (K2, V2) ;

3. chaque mapper agrège les valeurs associées à la même clé, créant ainsi des couples inter-

médiaires (K2, [V2]). En fonction des caractéristiques du système de fichier, l’ensemble des

valeurs associées à une même clé peuvent être regroupées dans un ou plusieurs fichiers, que l’on appelle des chunks. Une fonction de partitionnement est ensuite appliquée sur les clés pour répartir les chunks au reducers de sorte que tous les chunks d’une même clé soient envoyés au même reducer . La fonction de partition peut être personnalisée pour spécifier quelle clé doit être gérée par quel reducer ;

4. une fois qu’un mapper a traité son entrée, il en informe le superviseur ;

5. lorsque tous les mappers ont traité leur entrée, le superviseur informe les reducers pour lancer la seconde phase ;

6. les reducers agrègent les couples intermédiaires des différents mappers et construisent les entrées définitives de la fonction de reduce ;

7. les reducers exécutent la fonction de reduce sur chaque groupe de valeurs associées à chaque

clé (c’est-à-dire sur chaque couple (K2, [V2])) ;

8. les couples finaux clé-valeurs (K3, V3) sont écrits dans un fichier du système de fichiers

distribué ;

9. enfin, les reducers informent le superviseur de la localisation du résultat final. Lorsque tous les reducers ont terminé de traiter toutes les tâches de reduce, le travail est terminé. Sans prétraitement des données, il est impossible de savoir quel mapper va produire quelle clé. Cependant, il faut s’assurer que toutes les occurences d’une même clé soient envoyées au même

1. (X, Y ) dénote un couple de valeurs dont la première est de type X et la seconde de type Y . [X] dénote une liste d’éléments de type X.

3.2. Distribution du patron de conception MapReduce 41

Figure 3.1 : Flux de données et de contrôle MapReduce.

reducer afin de garantir la cohérence du résultat final. C’est pourquoi, qu’il soit réalisé par une

fonction par défaut ou par une fonction spécifique apportée par l’utilisateur, le partitionnement des tâches de reduce aux reducers est fixé a priori. Par exemple, pour déterminer quel reducer traitera une clé cle, la fonction de partition par défaut de Hadoop effectue un modulo sur le nombre de reducers :

cle.hashCode() % nombre_reducers

Exemple 3.1 (Job MapReduce : température moyenne).

Considérons le job MapReduce qui consiste à calculer la température moyenne de plusieurs villes. Pour ce faire, nous devons analyser des données qui contiennent des relevés de tempé- rature parmi d’autres informations. Les données d’entrée sont présentées dans le tableau3.1. Comme nous pouvons le voir, un relevé est composé d’une ville, d’une date et du relevé de température en lui-même.

Ces données sont analysées par un système de calculs constitué de deux nœuds n1 et n2.

Ces deux nœuds vont successivement être utilisés comme des mappers (m1 et m2) et comme des reducers (r1 et r2).

D’abord, les données d’entrée sont divisées en fragments et confiées aux mappers. m1 gère le

fragment 0 et m2 gère le fragment 1. Afin de calculer la température moyenne par ville, les mappers exécutent la fonction de map suivante :

map : (V ille,oC, Date) → [(V ille,oC)] Ce faisant,

42 Chapitre 3. Patron de conception MapReduce

• m1 crée les couples (Lille, 27), (P aris, 29) et (Lyon, 30) ;

• m2 crée les couples (Lille, 14), (P aris, 12) et (Lille, 2).

Ensuite, les mappers produisent des chunks pour chaque clé qu’ils ont rencontrées :

• m1 produit les chunks ρLille1 = (Lille, [27]), ρP aris1 = (P aris, [29]) et ρLyon2 = (Lyon, [30])

• m2 produit les chunks ρLille2 = (Lille, [14, 2]) et ρP aris2 = (P aris, [12]).

Afin de déterminer à quel reducer envoyer les chunks, les mappers utilisent une fonction de partition. Ici, r1 doit gérer les tâches qui concernent les villes de Lille et Lyon, et r2

doit gérer la tâche qui concerne Paris. En collectant l’ensemble des chunks associés à une clé, les reducers peuvent construire les entrées cohérentes pour la fonction de reduce afin d’avoir le résultat associé à cette clé. Par exemple, r1 collecte le chunk non local ρLille2 et

crée l’entrée (Lille, [27, 14, 2]) qui contient toutes les informations nécessaires au calcul de la température moyenne à Lille.

Pour finir, les reducers exécutent la fonction de reduce suivante afin d’obtenir le résultat du job :

reduce : (V ille, [oC]) → (V ille,oC)

Pour la ville de Lille, r1 calcule le résultat final 14, 3oC.

Ville oC Date du relevé

fragment 0 Lille 27 Juin Paris 29 Juin Lyon 30 Août fragment 1 Lille 14 Septembre Paris 12 Octobre Lille 2 Janvier

Tableau 3.1 : Données associées à l’exemple3.1.

Une étape optionnelle de combinaison peut être ajoutée afin d’alléger les données envoyées aux

reducers. Cette étape intervient entre les étapes 5 et 6 du flux de données décrit précédemment.

Elle nécessite que l’utilisateur renseigne une fonction de combinaison qui prétraite les résultats des mappers avant qu’ils soient envoyés aux reducers. L’étape de combinaison étant optionnelle, elle doit s’intégrer de manière transparente au flux des données de MapReduce. Elle produit

donc des données de type (K2, [V2]). Autrement dit, le rôle de la fonction de combinaison est

généralement de réduire la taille de la liste des valeurs associées à une clé en les agrégeant. Dans le cas d’une fonction de reduce associative et commutative (par exemple la somme, la multiplication ou le maximum), la fonction de combinaison est identique à la fonction de reduce.

Exemple 3.2 (Fonction de combinaison).

Considérons ici un job MapReduce dont la fonction de reduce consiste à calculer la valeur maximale associée à une clé. Après application de la fonction de map, un reducer reçoit deux chunks qui viennent des mappers m1 et m2 et qui concernent la clé cle :

• ρcle