• 20 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 17/10/2023

Allez au-delà de MapReduce avec Spark

Nous avons vu, dans la partie précédente, comment réaliser des calculs distribués avec MapReduce, dont Hadoop est une implémentation. A l'usage, Hadoop MapReduce présente deux inconvénients majeurs :

  1. Après une opération map ou reduce, le résultat doit être écrit sur disque. Ce sont ces données écrites sur disque qui permettent aux mappers et aux reducers de communiquer entre eux. C'est également l'écriture sur disque qui permet une certaine tolérance aux pannes : si une opération map ou reduce échoue, il suffit de lire les données à partir du disque pour reprendre là où on en était. Cependant, ces écritures et lectures sont coûteuses en temps.

  2. Le jeu d'expressions composé exclusivement d'opérations map et reduce est très limité et peu expressif. En d'autres termes, il est difficile d'exprimer des opérations complexes en n'utilisant que cet ensemble de deux opérations.

Apache Spark est une alternative à Hadoop MapReduce pour le calcul distribué qui vise à résoudre ces deux problèmes.

Spark vs Hadoop MapReduce

La différence fondamentale entre Hadoop MapReduce et Spark est que Spark écrit les données en RAM, et non sur disque. Ceci a plusieurs conséquences importantes sur la rapidité de traitement des calculs ainsi que sur l'architecture globale de Spark.

Pour mémoire, voici quelques ordres de grandeurs approximatifs relatifs au transfert de données en RAM et sur disque :

Technologie

Latence (s)

Taux de transfert (Go/s)

Disque dur

10⁻²

0.15

SSD

10⁻⁴

0.5

DDR3 SDRAM

10⁻⁸

15

Les différences de temps de transferts relevées entre la RAM et le disque laissent à penser qu'on peut aisément accélérer les opérations de lecture et écriture de données par un facteur 10⁴. Attention, cela ne signifie pas que nos calculs distribués vont soudainement être réduits d'autant ! Par exemple, le temps de réalisation des calculs distribués passé dans le processeur n'est pas affecté par le remplacement de l'écriture sur disque. Par ailleurs, les temps de transfert réseau doivent également être pris en compte et peuvent difficilement être réduits.

Ceci étant dit, on peut observer en passant de Hadoop à Spark une accélération des temps de traitement d'un facteur 10 à 100 ! Dit comme ça, ça peut sembler magique, mais le choix de stocker les données intermédiaires en RAM a des conséquences sur l'architecture même de Spark. En particulier, comment avec des données en RAM, garantir une tolérance aux pannes ? Dès qu'une machine devient indisponible, les données qu'elle stockait en RAM deviennent également indisponibles. Nous verrons plus tard que pour résoudre ce problème, avec Spark, les calculs sont distribués sous forme de graphe ; l'état d'un nœud peut être reconstitué à partir de ses nœuds voisins.

Les coûts engendrés par le déplacement des données du disque vers la RAM sont-ils inquiétants ? Effectivement, en 2004, quand Hadoop fut créé, une machine qui contenait plus de 4 Go de RAM était considérée comme une bête de course. Pour mémoire, la quantité de RAM recommandée pour Windows Vista, sorti en 2007, était de 1 Go. Aujourd'hui, 1 Go de RAM coûte moins de 10€ et il est courant de trouver des serveurs dotés de 256 Go de RAM. Il ne paraît donc pas insensé de stocker des téraoctets de données en RAM.

Enfin, Spark élargit le cadre map/reduce en proposant à l'utilisateur (vous !) des opérations supplémentaires pouvant être réalisées de manière distribuée. Nous verrons que Spark emploie diverses techniques d'optimisation, mais qu'au final tout calcul distribué est réalisé sous la forme d'opérations map/reduce. D'une certaine manière, MapReduce est le langage assembleur du calcul distribué : les outils permettant de réaliser des calculs distribués, tel Spark, permettent à l'utilisateur de s'abstraire de MapReduce ; tout comme les langages de programmation de haut niveau peuvent être compilés en assembleur mais permettent de ne pas avoir à écrire soi-même des programmes en assembleur.

Wordcount en Spark

Avant de voir plus en détails comment fonctionne Spark et comment l'utiliser pour distribuer des calculs sur des données massives, voyons comment réaliser le "Hello World!" du calcul distribué. J'ai nommé... le comptage de mots ! Ceci devrait vous donner une idée de ce à quoi ressemble une application Spark. Les applications Spark peuvent être créées en Java, Scala ou Python ; dans le reste de ce cours nous utiliserons principalement Python. N'hésitez pas à vous référer à la documentation officielle de Spark pour comprendre comment créer des applications Spark dans votre langage préféré.

from pyspark import SparkContext

# Instantiation d'un SparkContext
sc = SparkContext()

# Lecture d'un fichier texte : le fichier est décomposé en lignes.
lines = sc.textFile("text.txt")

# Décomposition de chaque ligne en mots
word_counts = lines.flatMap(lambda line: line.split(' ')) \
                   # Chacun des mots est transformé en une clé-valeur
                   .map(lambda word: (word, 1)) \
                   # Les valeurs associées à chaques clé sont sommées
                   .reduceByKey(lambda count1, count2: count1 + count2) \
                   # Le résultat est récupéré
                   .collect()

# Chaque paire (clé, valeur) est affichée
for (word, count) in word_counts:
    print(word, count)

Comme vous pouvez le voir, les opérations disponibles dans Spark sont très similaires à celles proposées par Hadoop MapReduce. Nous verrons, dans le chapitre suivant, comment installer Spark et exécuter ce programme.

Exemple de certificat de réussite
Exemple de certificat de réussite