API04 Contribution Apache Hadoop: Présentation et application dans le domaine des Data Warehouses Introduction Cette publication a pour but de présenter le framework Java libre Apache Hadoop, permettant notamment de faciliter la création d applications distribuées grâce à son traitement efficace de grandes quantités de données. Le Big Data est aujourd hui une réalité et divers exemples en témoigne. Le New York Times convertit 4 millions d articles en PDF en 36h (lien) et Facebook peut analyser aux alentours de 220 millions de profils en 11h (lien). Les performances de cet outil sont extrêmement bonnes, et on peut penser que dans le cadre des Data Warehouses, le traitement efficace d une grande quantité de données est un gain de temps considérable pour leur exploitation future. Architecture Hadoop est constitué de plusieurs modules et projets qui lui sont reliés. Parmi les principaux, on distingue les suivants : HDFS : un système de fichiers distribué permettant de stocker de large volume de données sur un grand nombre de machine. MapReduce : une implémentation de l algorithme permettant un traitement efficace des calculs parallèles. Apache HBase : une base de données distribuée disposant d un stockage adapté aux grandes volumétries. Apache Hive, Apache Pig : des logiciels d analyse de données permettant d utiliser Hadoop. On se limitera ici à comprendre le cœur de l architecture, à savoir Hadoop Distributed File System et MapReduce avant de voir plus en détail comment construire un programme Java utilisant ces concepts. 1
HDFS Une architecture HDFS, ou cluster HDFS repose sur deux types de composants : Un Namenode, gérant les métadonnées, l arborescence des fichiers, ainsi que l espace des noms. Un Datanode, stockant et restituant l ensemble des blocs de données grâce aux interrogations du Namenode. Le Namenode est le composant principal et est unique par cluster. Sans lui, on peut considérer que tous les fichiers sont perdus car il n existe pas de moyen de les reconstituer à partir d un bloc. Il centraliste la lecture mais aussi l écriture : cette dernière est propagée sur plusieurs Datanodes et permet la duplication sur différents nœuds et différentes machines. HDFS met en œuvre le pattern master- worker, un modèle de traitement parallèle d une ou de plusieurs opérations à travers plusieurs workers (=Datanode) et un master (=Namenode). Source : Site officiel http://hadoop.apache.org Le système HDFS intègre un mécanisme de failover pour les problèmes de pannes, et peut ainsi garantir la disponibilité et l intégrité des données malgré une défaillance système (plantage d une machine). C est pourquoi on parle de haute disponibilité des données. 2
Map/Reduce Comme on l a déjà évoqué, MapReduce est un modèle de programmation parallèle permettant de traiter un grand volume de données. Celui- ci s appuie sur deux étapes principales : le mapping et le reducing. Lors de l étape de Map, on définit une fonction de mapping dont le but sera d analyser les données en entrée telles qu elles sont fournies dans les blocs de données HDFS. Les données en sortie à l issue de cette étape sont des couples < clé, valeur > et on a au plus un couple pour chaque données en entrée (on peut choisir d exclure des données non valides par exemples). Suite à cette étape, il faut Reduce. On définit donc une fonction qui, à partir des résultats précédents, génère les données finales agrégées (comme le nombre d occurrence pour chaque clé). Il est important de noter que les nœuds se chargeant du mapping ne s occupe pas du reducing. Lors de cette dernière étape, chaque nœud traite une liste de données ayant toutes la même clé, ce qui permet de faire les calculs correspondant de manière répartie et efficace. Source : http://blog.khaledtannir.net Ainsi, lors de l étape de mapping, on envoie simplement les données vers les nœuds qui devront les traiter en fonction de leur clé. Afin d optimiser ce processus, on peut faire intervenir une étape intermédiaire et facultative appelée combining. 3
L étape du Combine n est autre qu un mini- reducing des données au sein d un nœud ayant effectué son mapping mais avant de les envoyer aux prochains nœuds pour le reducing. L avantage se fait au niveau de la bande passante dans le cas d un environnement distribué : plutôt que d envoyer n lignes ayant la même clé à un nœud donné, on envoie à ce dernier une seule ligne représentant l opération d agrégation déjà réalisée. Application au sein d un programme Java Voici les différentes étapes d un programme simple avec en gras ce qui doit être réaliser par le développeur : Configuration du job, de l unité de travail. Distribution du jeu de données sur le cluster HDFS (suppose d avoir le service en état de fonctionnement). Démarrage de chaque tâche map avec son propre jeu de données, issu de la distribution. Exécution en parallèle de chaque fonction map. Les sorties sont triées par clé, nouveau jeu de données. Démarrage de chaque tâche reduce avec son propre jeu de données, issu du tri. Exécution en parallèle de chaque fonction reduce. Assemblage des résultats du reducing puis stockage dans le cluster HDFS. Il y a donc très peu de paramétrisation à faire pour créer une tâche de MapReduce simple. Pour cela, il suffit de créer un programme Java depuis Eclipse et de disposer du plugin Hadoop MapReduce. Il faut également télécharger les dépendances sur le site officiel pour les imports. Voilà à quoi ressemble le programme Java adapté à la vente des jolitres (première version, amélioration à venir) depuis l exemple fourni sur le site officiel. public class JolitreCount { JolitreCount.java protected static Logger logger = Logger.getLogger(JolitreCount.class); public static void main(string[] args) { JobClient client = new JobClient(); JobConf conf = new JobConf(JolitreCount.class); // specify output types conf.setoutputkeyclass(text.class); conf.setoutputvalueclass(intwritable.class); // specify input and output dirs TextInputFormat.addInputPath(conf, new Path("input")); TextOutputFormat.setOutputPath(conf, new Path("output")); // specify a mapper 4
conf.setmapperclass(jolitrecountmapper.class); // specify a reducer conf.setreducerclass(jolitrecountreducer.class); conf.setcombinerclass(jolitrecountreducer.class); client.setconf(conf); try { // job time long start_time = System.nanoTime(); JobClient.runJob(conf); long end_time = System.nanoTime(); double seconds = (end_time - start_time)/1e9; logger.info("task completed in " + seconds); catch (Exception e) { e.printstacktrace(); JolitreCountMapper.java public class JolitreCountMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> { private final IntWritable one = new IntWritable(1); private Text word = new Text(); @Override public void map(longwritable arg0, Text value, OutputCollector<Text, IntWritable> output, Reporter arg3) throws IOException { String[] line = value.tostring().split(";"); if(!"".equals(line[2]) &&!" ".equals(line[2])) word.set(line[2]); output.collect(word, one); JolitreCountReducer.java public class JolitreCountReducer extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> { public void reduce(text key, Iterator values, OutputCollector output, Reporter reporter) throws IOException { int sum = 0; while (values.hasnext()) { IntWritable value = (IntWritable) values.next(); sum += value.get(); // process value output.collect(key, new IntWritable(sum)); 5
Sources http://hadoop.apache.org/ http://en.wikipedia.org/wiki/apache_hadoop http://www.coreservlets.com/hadoop- tutorial/ http://developer.yahoo.com/hadoop/tutorial/ http://blog.khaledtannir.net http://blog.inovia- conseil.fr/?p=67 http://hortonworks.com/hadoop- tutorial/hello- world- an- introduction- to- hadoop- hcatalog- hive- and- pig/ 6