Site icon Blog Zenika

Hadoop, première partie : Le système de fichier et le MapReduce au service des gros volumes de données

Nous allons parler dans ce billet d’Hadoop, le framework Java d’Apache en vogue pour le traitement de données très volumineuses (pouvant aller jusqu’à plusieurs pétaoctets). Ce framework implémente notamment sa propre version de l’algorithme MapReduce, qui a été instauré par Google.

 

Nous allons donc d’abord présenter rapidement deux concepts fondamentaux d’Hadoop : son système de fichiers, ainsi que l’algorithme de MapReduce, et ensuite nous illustrerons cela par un exemple simple, avant d’aller plus loin dans de prochains articles.

  • Le système de données distribué d’Hadoop : le HDFS
Hadoop utilise un système de fichiers virtuel qui lui est propre : le HDFS (Hadoop Distributed File System), et qui se décompose en un namenode (le maître) et plusieurs datanodes (les noeuds de données).
Les datanodes regroupent les blocs de données en les répliquant (ci-dessous, les blocs sont tous répliqués trois fois). Le namenode, quant à lui, va orchestrer les données, et contient les informations concernant l’emplacement des différentes répliques. Le secondary namenode  sert à effectuer des checkpoints réguliers du namenode, afin de les réutiliser en cas de problème. Ci-dessous un schéma expliquant les différents noeuds du HDFS :
 

  • l’algorithme de MapReduce dans Hadoop :
Le MapReduce est une technique qui décompose le traitement d’une opération (appelée « job » chez Hadoop) en plusieurs étapes, dont deux élémentaires, afin d’optimiser un traitement parallèle des données.

i. Le « Mapping » :

Cette étape accomplit une opération spécifique sur chaque élément de la liste en input : à partir d’une liste sous la forme <clé,valeur>, il génère alors une liste en output sous la même forme :

ii. Le « Reducing » :

L’opération qui se situe après le Mapping et le Reducing est appelée le Shuffling, et réarrange les éléments de la liste afin de préparer le Reducing.
Le traitement voulu est alors effectué, donnant l’output final :
  • Un exemple de traitement de MapReduce avec Hadoop :
Nous avons donc pu nous familiariser avec les concepts clés d’Hadoop, il est temps d’illustrer cela par un exemple. Nous n’avons pas un pétaoctet de données sous la main, mais nous allons profiter de la prolifération de l’open data pour effectuer un petit traitement sur des données simples. Le site open data de nos amis belges data.gov.be donne librement accès à de nombreuses données, comme par exemple la liste des différents prénoms recensés en Belgique en 2007, qui se présente sous la forme d’un fichier Excel contenant plus de 38 000 entrées.
Ces données existent aussi pour les femmes, nous avons tout concaténé afin d’avoir un fichier .csv regroupant tous les prénoms belges en 2007, hommes et femmes, sous la forme (Nom,Nombre d’apparitions) :


 
Traitement des données :
Le traitement que nous voulons faire est simple : nous voulons avoir le nombre de personnes par lettre de l’alphabet en Belgique. Pour ce faire, il suffit de créer une fonction Map et une fonction Reduce adaptée à nos besoins, et sous la bonne forme (clé,valeur), afin qu’Hadoop puisse alors effectuer le traitement.

Voici comment vont être réalisées les différentes opérations :

 

Implémentation en Java des méthodes Map et Reduce :

public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
       public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
              String[] tokens = value.toString().split(",");
              String cle = tokens[0].substring(0,1);
              int valeur = Integer.parseInt(tokens[1]);
              context.write(new Text(cle), new IntWritable(valeur));
       }
}
public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {
       public void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException,InterruptedException {
              int sum = 0;
              for (IntWritable val : values) {
                   sum += val.get();
              }
       context.write(key, new IntWritable(sum));
       }
}

 

Nous pouvons maintenant exporter en un jar executable, qu’on va ensuite pouvoir lancer avec Hadoop. Mais tout d’abord, il faut que le fichier en entrée (pour nous la liste des prénoms et le nombre d’apparitions correspondantes) soit dans le HDFS. Pour ce faire, il suffit d’utiliser la gestion du HDFS par ligne de commande :

hadoop fs -mkdir /input
hadoop fs -put /repertoire_local/noms_belges.csv /input

 

Nous pouvons alors éxécuter le jar via Hadoop, en demandant que le fichier de sortie soit crée dans le dossier output du HDFS, qui sera alors créé. Il suffit alors de récupérer ce fichier en local sachant que, par défaut, le fichier est nommé « part-r-00000 » :

hadoop jar /repertoire_local/exemple.jar /input/noms_belges.csv /output
hadoop fs -get /output/part-r-00000 /repertoire_local_sortie

 

Voici un aperçu du fichier obtenu :

Nous avons donc pu voir les possibilités offertes par Hadoop pour le traitement distribué des données, et sa simplicité de mise en oeuvre.
Pour plus d’informations, vous pouvez consulter la documentation d’Apache, ou le très complet « Hadoop : The Definitive Guide« , de Tom White.

Auteur/Autrice

Quitter la version mobile