Vous êtes sur la page 1sur 7

Cours Big Data

Application2 : Initiation à Spark

Objectifs :

Introduction à Apache Spark, exemples d’utilisation


et performance

Spark: http://spark.apache.org/
Inspirée du blog de Cloudera:
http://blog.cloudera.com/blog/2013/11/putting-spark-to-use-fast-in-memory-
Inspirée du blog de Cloudera:
http://blog.cloudera.com/blog/2013/11/putting-spark-to-use-fast-in memorycomputing-
for-your-big-data-applications/
Srini Penchikala: Traitements Big Data avec Apache Spark,
http://www.infoq.com/fr/articles/apache-spark-introduction

1
I. Apache Spark

I.1 Spark vs MapReduce

Apache Spark a été créé au départ pour pallier les limitations de Hadoop Map/Reduce. En effet, ce
dernier, qui s’avère être idéal pour implémenter des applications à base de traitements par lot(batch
processing), montre certaines limites quand il s’agit d’applications à faible latence et à traitements
itératifs, comme par exemple pour le machine learning ou pour les algorithmes à base de graphes.
Spark permet de généraliser le modèle de traitement de Map-Reduce, tout en améliorant de manière
conséquente les performances et l’utilisabilité. Il permet aux développeurs d’écrire des applications en
composant facilement des opérateurs tels que des mappers, reducers, jointures, group-bys et filtres.
Cette composition facilite l’expression d’un ensemble large de traitements.

De plus, Spark garde la trace des données que chacun de ces opérateurs produit, et permet aux
applications de stocker ces données en mémoire, améliorant ainsi considérablement la performance en
permettant d’éviter les accès coûteux au disque. Hadoop Map Reduce est efficace pour les traitements
à passe unique (un seul passage sur les données), mais pas pour des traitements à plusieurs passes.

Pour ces traitements plus complexes, il faut enchaîner une série de jobs Map-Reduce et les exécuter
séquentiellement, chacun de ces jobs présentant une latence élevée et aucun ne pouvant commencer
avant que le précédent ne soit totalement terminé. Avec Spark, il est possible de développer des
pipelines de traitement de données complexes, à plusieurs étapes en s’appuyant sur des graphes
orientés acycliques (DAG : Directed Acyclic Graph). Spark permet de partager les données en
mémoire entre les graphes, de façon à ce que plusieurs jobs puissent travailler sur le même jeu de
données3.

I.2 Architecture de Spark

Les applications Spark s’exécutent comme un ensemble de processus indépendants sur un cluster,
coordonnés par un objet SparkContext du programme principal, appelé Driver Program.

2
Pour s’exécuter sur un cluster, le SparkContext se connecte à un Cluster Manager, qui peut être soit un
gestionnaire standalone de Spark, soit YARN ou Mesos, pour l’allocation de ressources aux
applictions. Une fois connecté, Spark lance des executors sur les noeuds du cluster, des processus qui
lancent des traitements et stockent les données pour les applications. Il envoie ensuite le code de
l’application (Jar ou ficher python) aux executors. SparkContext envoie ensuite les Tasks aux
executors pour qu’ils les lancent.

I.3 RDD : Resilient Distributed Datasets

Les RDD sont une représentation abstraite des données en mémoire, permettant aux programmeurs de
réaliser des traitements in-memory sur de larges clusters, avec une tolérance aux fautes importante.
Elle est assimilée à une table dans une base de données. Un RDD peut porter tout type de données et
est stocké par Spark sur différentes partitions. Les RDD permettent de réarranger les calculs et
d’optimiser les traitements.

3
I.4 Traitement dans Spark

Spark fournit également des traitements Map-Reduce, mais en exploitant efficacement la mémoire,
tout en utilisant le lineage en cas d’échec si nécessaire.
Les étapes de shuffle dans spark sont moins coûteuses, car faites en mémoire. Il supporte également
les évaluations paresseuses (lazy evaluation) des requêtes, ce qui veut dire que les transformations ne
s’exécutent sur le cluster que si une action est invoquée. Cela dit, Spark peut utiliser le disque pour des
opérations intermédiaires si la mémoire n’est pas suffisante. Il est ainsi capable d’alterner les
traitements sur mémoire et sur disque.

II. Partie Pratique :

Par défaut, Spark utilise Scala (http://www.scala-lang.org/ ), un langage qui combine les paradigmes
orienté-objet et fonctionnel. Il est compilé en bytecode Java.

Note :

Vous allez travailler avec la machine Virtuel cloudera-quickstart-vm-5.3.0-0-virtualbox (fournie


par votre ensegnant)

II.1 Spark Shell

1. Lancez l’interpréteur de commandes spark-shell en entrant

$ spark-shell

2. Créez une liste Scala d’entiers de 1 à 1000

scala> val xs = (1 to 1000).toList

xs: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,...

3. Créez un RDD de la liste Scala xs déjà créée

scala> val xsRdd = sc.parallelize(xs)

xsRdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[52] at parallelize at <console>:19

4. Filtrez maintenant les nombres pairs dans le RDD nouvellement créé à l'aide de Spark.
scala> val evenRdd = xsRdd.filter{ _ % 2 == 0}

evenRdd: org.apache.spark.rdd.RDD[Int] = FilteredRDD[53] at filter at <console>:21

4
N'oubliez pas que la méthode de filtrage de la classe RDD est une transformation. Comme il
s’agit d’une opération lazy, Spark n’applique pas immédiatement la fonction anonyme que
vous avez transmise à la méthode de filtrage. Une action qui est souvent utilisée avec les RDD
est « count ».

5. Il retourne le nombre d'éléments dans un RDD.


scala> val count = evenRdd.count

count: Long = 500

6. L’action “first” retourne le premier élément dans evenRdd:


scala> val first = evenRdd.first

first: Int = 2

7. L’action “take(5)” retourne les cinq premiers éléments de l’objet evenRdd :


scala> val first5 = evenRdd.take(5)

first5: Array[Int] = Array(2, 4, 6, 8, 10)

II.2 Exemple : Word Count avec Python

L’exemple que nous allons dérouler est le célèbre WordCount, l’exemple MapReduce
Classique. Cet exemple permet de calculer le nombre d’occurrence de mots.
Si on utilisait MapReduce, on aurait besoin de deux jobs successifs, et les données seraient
persistées sur HDFS entre les deux. En contre partie, dans Spark, un seul job est nécessaire,
avec presque 90% moins de lignes de code.

Voici le code en python de l’exemple (fourni par votre enseignante) :

5
import sys

from pyspark import SparkContext, SparkConf

if __name__ == "__main__":

# create Spark context with necessary configuration


sc = SparkContext("local","PySpark Word Count Exmaple")

# read data from text file and split each line into words
words = sc.textFile("./text.txt").flatMap(lambda line: line.split(" "))

# count the occurrence of each word


wordCounts = words.map(lambda word: (word, 1)).reduceByKey(lambda a,b:a +b)

# save the counts to output


wordCounts.saveAsTextFile("./output/")

Créez également un fichier text.txt contenant quelques lignes :

echo "Sur mes cahiers d'écolier Sur mon pupitre et les arbres Sur le sable de neige J'écris ton nom" >
text.txt
echo "Sur les pages lues Sur toutes les pages blanches Pierre sang papier ou cendre J'écris ton nom" >>
text.txt
echo "Sur les images dorées Sur les armes des guerriers Sur la couronne des rois J'écris ton nom" >>
text.txt

Lancer l’exécution de l’application avec spark-submit. Le script spark-submit permet


d’utiliser tous les cluster managers que Spark sait gérer, de façon transparente à l’application.
Dans une fenêtre terminal (bash), entrez:
spark-submit ./wordcount.py

Note : les applications spark peuvent également être écrites en java ou en scala. une fois vous avez
compile et package votre application e un fichier.jar vous pouvez exécuter votre application avec une
commande similaire:

$ spark-submit --class NomDeMaClasse chemin/vers/monapplication.jar

Un dossier output est construit automatiquement pour contenir le résultat de l'exécution.

('neige', 1)
('arbres', 1)
('armes', 1)
('Sur', 8)
('images', 1)
.........

6
III Architecture de l'environnement d'exécution

Jusqu'à présent, nous avons executé des applications Spark en local, et vous pensez peut-être
que cela présente peu d'intérêt puisque nous cherchons à distribuer des calculs sur plusieurs
machines. Cependant, vous n'aurez pas à réécrire vos applications locales avant de les
distribuer sur plusieurs machines ; la couche d'abstraction que fournit Spark vous permet de
ne pas vous soucier de l'architecture sur laquelle tourne votre application. Cela vous permet
de prototyper des applications en local avant de les envoyer vers un cluster de plusieurs
machines pour traiter des données de taille plus conséquente sans vous préoccuper du
changement d'architecture. Vous pourrez donc utiliser votre environnement local pour
déboguer vos applications distribuées, ce qui est tout de même bien pratique.

Par ailleurs, en arrière plan, Spark a en fait déjà parallélisé votre application si vous disposez
de plusieurs cœurs sur votre processeur. Pour observer la différence de vitesse de traitement,
exécutez les commandes suivantes :

# Utilisation de tous les cœurs disponibles


$ time spark-submit ./wordcount.py

# Utilisation d'un seul cœur


$ time spark-submit --master local[1] ./wordcount.py

Pour observer une différence notable, vous devrez utiliser un texte assez long

Vous aimerez peut-être aussi