Développement de programmes MapReduce

les principes de fonctionnement de MapReduce restent valables quel que soit le langage de programmation utilisé.

Un programme Hadoop se divise généralement en trois parties :

  • Le driver, qui s’exécute sur une machine client, est chargé de configurer le job puis de le soumettre pour exécution.
  • Le mapper est chargé de lire les données stockées sur disque et les traiter.
  • Le reducer est chargé de consolider les résultats issus du mapper puis de les écrire sur disque.

1 – Les entrées-sorties

Dans MapReduce, les données sont toujours lues ou écrites selon le format <key, value> (<clef, valeur>).

Les données lues par le mapper sont définies au niveau du driver. La définition des données comprend :

  • Leur localisation (fichier ou répertoire).
  • Le type des enregistrements, qui est défini par la classe InputFormat.
  • La détermination de la taille des InputSplits : un InputSplit définit le volume des données qui seront lues à chaque opération de lecture.

Hadoop prend en compte par défaut les types d’enregistrement suivants :

  • TextInputFormat :
    • value est une ligne entière terminée par \n
    • key est l’offset de la ligne depuis le début de fichier
  • KeyValueTextInputFormat:
    • Chaque ligne est supposée être au format <key><separator><value>\n.
    • Le separateurr par défaut est tab.
  • SequenceFileInputFormat :
    • Permet de lire un fichier binaire de paires <key, value>, comprenant éventuellement des métadonnées.
  • SequenceFileAsTextInputFormat :
    • • Format identique au précédent mais, en plus, convertit les clefs et les valeurs en strings (<key.toString(), value.toString()>).

Dans Hadoop:

  • Les clefs sont des objets qui implémentent l’interface ComparableWritable.
  • Les valeurs sont des objets qui implémentent l’interface Writable.

Par défaut, Hadoop propose les types de données suivants :

  • IntWritable (int en Java).
  • DoubleWritable (double en Java).
  • Text (string en Java).
  • etc.

2 – La phase map (exemple 1)

Nous allons utiliser le programme WordCount pour expliquer le fonctionnement d’un mapper ainsi que celui d’un reducer. Le programme WordCount est écrit en pseudo-code et est simplifié à l’extrême.

Il s’agit de concevoir un programme Hadoop comptant le nombre d’occurrences des différents mots composant un livre.

Voici le contenu du fichier (livre) en entrée :

Lorem ipsum dolor sit
nec et nec et ultrices
Pellentesque et Pellentesque et bibendum
Lorem ipsum dolor sit

Un enregistrement correspond à une ligne terminée par \n. Dans un véritable programme Hadoop, on utilisera le format TextInputFormat pour lire les enregistrements.

Ci-dessous le mapper du programme WordCount :

Explication :

Ligne 1 : le mapper lit en entrée un enregistrement sous la forme d’un couple <key, value> avec :

  • value du type String (c’est une ligne du fichier).
  • key du type LongWritable (c’est l’offset de la ligne depuis le début du fichier).

ligne 2 : pour chaque mot w de la ligne en cours…

Ligne 3 : on écrit dans un fichier en sortie le couple <w, 1>, 1 correspondant à une occurrence du mot contenu dans la variable w.

Le fichier en sortie de mapper sera donc le suivant :

Lorem,1
ipsum,1
dolor,1
sit,1
nec,1
et,1
nec,1
et,1
ultrices,1
Pellentesque,1
et,1
Pellentesque,1
et,1
bibendum,1
Lorem,1
ipsum,1
dolor,1
sit,1

3 – Entre la phase map et la phase reduce (exemple 1)

Avant d’être envoyé au reducer, le fichier est automatiquement trié par clef par Hadoop : c’est ce que l’on appelle la phase de “shuffle & sort”. Le fichier en entrée du reducer est le suivant :

Lorem,[1,1]
ipsum,[1,1]
dolor,[1,1]
sit,[1,1]
nec,[1,1]
et,[1,1,1,1]
ultrices,[1]
Pellentesque,[1,1]
bibendum,[1]

4. La phase reduce (exemple 1)

Ci-dessous le reducer du programme Hadoop permettant de consolider les résultats issus du mapper :

Explication :

Ligne 1 : le reducer prend en entrée un enregistrement sous la forme d’un couple <key, value> avec :

  • key du type Text (c’est un mot).
  • value étant une liste de valeurs du type intWritable.

Ligne 2 : le reducer remet à zéro le compteur wordCount lorsque l’on change de mot.

Ligne 3 et 4 : pour chaque valeur v dans la liste inValue2 on ajoute v à wordCount.

ligne 5 : quand on change de mot, on écrit dans un fichier en sortie le couple <inKey2, wordCount>, wordCount étant le nombre d’occurrences du mot contenu dans la variable inKey2.

Le fichier en sortie de reducer sera donc le suivant :

Lorem,2
ipsum,2
dolor,2
sit,2
nec,2
et,4
ultrices,1
Pellentesque,2
bibendum,1

Nous venons d’écrire notre premier programme Hadoop, permettant de compter le nombre d’occurrences des différents mots composant un livre !

  • Un job Hadoop comprend au minimum un mapper : il peut ne pas comprendre de phase reduce.
  • Durant la phase de shuffle & sort, tous les mappers sont susceptibles d’envoyer des données vers tous les reducers.

fonctionnement globale de mapreduce

Présentation et fonctionnement de MapReduce

Une bonne compréhension de MapReduce implique la maitrise du fonctionnement de Hadoop et HDFS. Pour cela, ces deux articles sont obligatoires pour mieux appréhender la suite du cours.

Qu’est ce que MapReduce ?

MapReduce est un modèle de programmation conçu spécifiquement pour lire, traiter et écrire des volumes de données très importants. Les programmes adoptant ce modèle sont automatiquement parallélisés et exécutés sur des clusters (grappes) d’ordinateurs. MapReduce consiste en deux fonctions map() et reduce().

map” est le nom d’une fonction de haut niveau qui applique une fonction donnée à chacun des éléments d’une liste et retourne une liste. Par exemple :

(mapcar #’round ‘(1.3 2.7 3.4 4.5)) => (1 3 3 4)

reduce” est le nom d’une fonction de haut niveau qui applique une fonction donnée à tous les éléments d’une liste et retourne une liste unique. Par exemple :

(reduce #’+ ‘(1 2 3 4)) => 10

MapReduce implémente les fonctionnalités suivantes :

  • Parallélisation automatique des programmes Hadoop.
    • HDFS se charge de la répartition et de la réplication des données ;
    • Le maître divise le travail en jobs parallèles et les répartit ;
    • Le maître collecte les résultats et gère les pannes des noeuds.
  • Gestion transparente du mode distribué.
  • Tolérance aux pannes.

Tout l’intérêt de ce modèle de programmation est de simplifier la vie du développeur Hadoop, en lui masquant le fonctionnement interne de Hadoop (parallélisation , tolérance aux pannes,…etc). Ainsi, le modèle de programmation permet au développeur de ne s’intéresser qu’à la partie algorithmique. Il transmet alors son programme MapReduce développé dans un langage de programmation au framework Hadoop pour l’exécution.

Fonctionnement de MapReduce

Un programme MapReduce se compose des trois parties suivantes

  • Le driver, qui s’exécute sur une machine client, est responsable d’initialiser le job puis de le soumettre pour exécution.
  • Le mapper est responsable de lire les données stockées sur disque et les traiter.
  • Le reducer est responsable de consolider les résultats issus du mapper puis de les écrire sur disque.