Le 14 septembre 2017, nous avons publié une version actualisée de notre Politique de confidentialité. En utilisant video2brain.com vous vous engagez à respecter ces documents mis à jour. Veuillez donc prendre quelques minutes pour les consulter.

Développer une application Big Data avec Hadoop

Résoudre le problème du secondary sort

TESTEZ LINKEDIN LEARNING GRATUITEMENT ET SANS ENGAGEMENT

Tester maintenant Afficher tous les abonnements
Dans cette vidéo, vous utiliserez la phase de tri de MapReduce pour trier les données arrivant aux reducers.
12:38

Transcription

Le secondary sort est un design pattern en MapReduce, qui permet réellement de profiter de l'étape de tri qui a lieu entre le Mapper et le Reducer, pour trier des données complémentaires aux clés. L'idée ici, est que l'on veut trier par exemple, les valeurs qui vont apparaitre dans le Reducer, ou du moins, l'une des parties des valeurs dans le cadre où la valeur est une clé composite. Au lieu de récupérer l'ensemble de ces valeurs dans le IntReadable du Reducer, et d'appliquer un tri une fois qu'on les a tous chargés en mémoire, notre objectif va être de profiter du tri qu'il a automatiquement lors de la phase de [...] lors du MapReduce et de laisser Hadoop trier nos valeurs avec nos clés. Alors pour résoudre ce problème, il faut faire pas mal d'opérations, la première étant de passer la valeur en plus à trier dans la clé de réaliser un comparateur qui permet à Hadoop de trier sur la clé qui va inclure désormais la valeur, puis de dire à Hadoop d'utiliser un autre tri, pour grouper les valeurs, et donc, de ce fait, pour grouper les valeurs, même si la clé est différente. Alors commençons simplement en rajoutant dans notre TwoDimensionsWritable, la notion de valeur qui sera pour nous un INT. On va donc rajouter le INT VALUE directement dans notre classe et de la même façon que l'on a fait pour Dim1 et Dim2, on va donc mettre l'attribut le remplir dans Constructeur et surtout donc, l'écrire dans le readFiles et dans le Write. Alors on va aussi rajouter les getters et les setters, toujours grâce à la génération par Eclipse. Donc nous avons nos getters et setters, et nous pouvons ici, directement rajouter désormais notre Value dans readFields. Alors on va donc faire un value qui est égal à WritableUtils.readVInt Alors le VInt ici correspond à l'Integer à taille variable, qui permet de gagner de la taille et de ce fait-là, également, du temps, puisque toutes les données vont transiter sur les autres. Moins il y a de données et plus c'est rapide. Dans le cadre du Write, on va faire un WritableUtils.writeVInt donc directement sur out et on va écrire Value. Nous venons de faire la sérialisation et la désérialisation, nous pouvons désormais adapter le CompareTrue et nous allons faire la comparaison sur la Dim2, et si jamais, elle est différente de 0, on la retourne sinon on va comparer les deux valeurs. Alors pour cela, on peut s'appuyer sur la méthode statique Compare de la classe Integer. Elle prend de Int, soit pour nous value et 0 pour GetValue. Nous allons également adapter la méthode Equals, donc en rajoutant simplement un Value==o.GetValue. Alors il nous faut cependant bien caster o au préalable. Nous allons également adapter la méthode Hcode. Pour cela, c'est relativement simple, on va faire le Value fois un autre nombre premier, par exemple, 37. Nous venons d'adapter notre TwoDimensionsWritable pour rajouter la valeur dedans, il va falloir la passer en supplément dans le Mapper, alors tout simplement ici, on va passer en plus mValue, et nous allons pouvoir commencer à créer des comparatifs. Or les comparateurs sont des classes qui permettent de comparer des objets Writable, donc pour nous, des TwoDimensionsWritable. Pour cela, on créée une classe que l'on va appeler TowDimensionsSortComparator, qui va être le comparateur utilisé pour le tri. Et qui va devoir étendre la classe WritableComparator. Donc nous avons ici notre classe il va nous falloir deux choses. La première, c'est faire le constructeur qui va appeler le constructeur parent, en précisant, à la fois, le type qui va être comparé, donc un TwoDimensionsWritable, et qui va préciser un booléen, pour savoir s'il va falloir désérialiser l'objet afin de le comparer, en l'occurrence, pour notre cas, on va mettre True, afin d'avoir les objets directement, désérialisés. On va faire la méthode Compare qui va travailler directement sur des Writable, Comparable. Voilà, et nous allons caster automatiquement nos objets, afin de récupérer des TwoDimensionsWritable. Alors nous le faisons à la fois pour A et B que nous allons mettre pour nous dans o1 et o2. Alors nous allons comparer et toujours de la même manière, donc je vous remets directement ici, le code de comparaison. Alors cela consiste à comparer d'abord, la Dim1, si elle est égale à 0, dans ce cas-là, on compare la Dim2, et si elle est égale à 0, dans ce cas-là, on va comparer la valeur. On va rajouter un SuppressWarning pour le raw type, et nous avons notre SortComparator qui est réalisé. À présent, il va nous falloir le GroupingComparator. Donc c'est un comparateur de la même façon. Un WritableComparator qui va tavailler sur les TwoDimensionsWritables mais qui va servir à grouper les clés, notamment pour être appelées ensuite en groupe sur les Reducers. Alors on va appeler ça un TwoDimensionsGrouping Comparator. Et nous allons éditer la classe, tout ce que nous avons à faire fondamentalement est de retourner directement ceci et de ne pas comparer du tout sur les valeurs. Ainsi si la Dim1 et la Dim2 sont égales, on va considérer que les objets du DimensionsWritable sont égaux. Et donc ils vont être dans le même groupe. Il nous reste encore au minimum une classe à faire qui est un Partionneur. Le partitionneur va permettre de répartir les différents groupes, directement sur les différents Reducers. L'idée ici est de prendre une clé et de dire sur quel Reducer elle va aller, pour qu'ensuite elle soit triée sur le Reducer et donc groupée sur le Reducer. Alors on va faire une classe MyPartitioner qui va étendre la classe Partitioner directement de org.apache.hadoop.mapreduce. Nous créons notre classe. Le partitionneur va travailler sur un ensemble de clés-valeurs. Donc ici, un TwoDimensionsWritable en clé. Et un IntWritable en valeur. Et nous allons faire la méthode GetPartition, qui va donc récupérer un TwoDimensionsWritable, en clé et un IntWritableValue en valeur. On a également en paramètres, un Int numPartition qui permet de savoir combien de partitions nous devons faire. Nous devons alors retourner un numéro entre 0 et numPartition correspondant à la partition qu'il va devoir traiter. Donc, cette fameuse clé-valeur. Donc pour cela, nous allons faire un return, et nous allons générer le numéro de partition à partir de notre clé. Cependant, nous n'allons pas prendre tous les éléments de la clé mais uniquement ceux qui nous intéressent, c'est-à-dire la Dim1 et la Dim2, sans prendre du tout la Value. Alors la méthode courante pour ce faire, c'est de baser sur le Hcode. C'est pour cela qu'il est très important sous Hadoop d'avoir des Hcodes, valables pour chacun des Writables Comparables. Et donc nous prenons le Hcode de la Dim1, nous prenons le Hcode en plus de la Dim2. Alors nous ajoutons un nombre premier pour le Hcode de la Dim1. Et nous avons désormais un entier, et nous voulons limiter à un certain nombre de partitions, donc nous pouvons donc réaliser un modulo sur le numPartition. Nous allons alors avoir un entier qui va être retourné entre 0 et numPartitions et qui va dépendre de la Dim1 et de la Dim2 de notre clé. C'est ce que l'on veut. On n'a plus qu'à appeler le code dessus. Alors pour cela nous modifions notre driver. Et nous allons ajouter ces différentes propriétés. Alors notamment, on a par exemple, un setGroupingComparator qui va être un TwoDimensionsGroupingComparator.class TwoDimensionsGroupingComparator.class On va faire également un setPartioner, donc setPartitionerClass qui va être le myPartitioner.class et enfin, un setSortComparatorClass, qui va donc être un TwoDimensionsSortComparator.class Alors tout l'objectif de ce code est d'avoir dans le Reducer, les valeurs qui sont directement triées, et donc on va pouvoir les exploiter pour réaliser des opérations supplémentaires. Notamment, on va pouvoir ajouter par exemple, l'opération MIN, qui va être de façon très simple uniquement la première valeur puisque l'on sait que les valeurs sont désormais triées par ordre croissant. On peut rajouter de la même façon l'opération MAX, qui va être la dernière valeur. Alors pour cela, l'on va de façon simple Iterer sur notre objet Iterable et récupérer la dernière. Enfin, toutes les récupérer, en l'occurrence. Ou on peut rajouter Range, par exemple, donc qui consiste à récupérer le MIN et le MAX et de faire la différence entre les deux. Comme nous pouvons le voir, le problème du Secondary Sort est complexe à gérer et nécessite un grand nombre de classes Java. Cependant, il est très puissant et il permet de profiter réellement de l'étape du [...] du MapReduce, pour incrémenter notre valeur dans le Reducer et pour pouvoir profiter de ce tri, directement sans avoir à le refaire.

Développer une application Big Data avec Hadoop

Concevez une application Big Data avec la suite Hadoop. Stockez des données dans l'HDFS et dans HBase, traitez-les en MapReduce sous YARN, exportez-les dans MySQL via Sqoop, etc.

2h31 (25 vidéos)
Aucun commentaire n´est disponible actuellement
 

Votre formation est disponible en ligne avec option de téléchargement. Bonne nouvelle : vous ne devez pas choisir entre les deux. Dès que vous achetez une formation, vous disposez des deux options de consultation !

Le téléchargement vous permet de consulter la formation hors ligne et offre une interface plus conviviale. Si vous travaillez sur différents ordinateurs ou que vous ne voulez pas regarder la formation en une seule fois, connectez-vous sur cette page pour consulter en ligne les vidéos de la formation. Nous vous souhaitons un excellent apprentissage avec cette formation vidéo.

N'hésitez pas à nous contacter si vous avez des questions !