Dans l’univers du Big Data, ces deux technologies font le buzz! Au delà de l’effet de mode essayons d’y voir un peu plus clair, en particulier sur les promesses annoncées par leurs concepteurs.
Commençons par Scala
La première version est née en 2003 à l’EPFL en Suisse où enseigne le Professeur Martin Odersky concepteur de Scala. C’est un langage de programmation de la famille des langages fonctionnels qui est de plus orienté objet et s’intègre nativement au langage Java.
Tout cela est très bien mais quels sont les bénéfices de Scala?
Ce langage s’appuie largement sur la notion de fonctions d’ordre supérieur.
Ces fonctions permettent de séparer clairement:
- la création d’un objet
- de sa manipulation future dans une application plus élaborée.
De plus, de nouveaux usages de ces objets peuvent être facilement ajoutées sans que cela soit lié à leur logique de création. On y reviendra sur des exemples plus concrets.
Par conséquent, le bénéfice que nous obtenons en utilisant des fonctions d’ordre supérieur est le « Don’t Repeat Yourself » ou DRY: le code produit par les développeurs Scala respecte ce principe.
Il devient plus simple de réutiliser à l’infini du code de façon optimale. Les équipes de concepteurs conservent alors des fonctions robustes dans leurs propres boites à outils, fonctions que l’on peut mettre en oeuvre à tout moment dans un nouveau contexte projet.
Cela plaide également pour un autre bénéfice de Scala, à savoir la concision du code produit par les concepteurs.
On attribue généralement à Steve Jobs la citation:
« Les seules lignes de codes que vous n’aurez jamais à déboguer, sont celles que vous n’aurez jamais écrites ».
Ce qui apparait comme un truisme, est pourtant plus profond qu’il n’y parait et tout développeur qui a englouti des heures à la recherche d’un bug dans du code abscons, peu lisible et non documenté appréciera…
On ne parle que des développeurs, et le Big Data dans tout cela?
Nous y arrivons.
La représentation des données et la manipulation de grandes collections de données sont au coeur des problématiques de la collecte et du traitement des données complexes et en volume. Le Big Data!
En effet, un grand nombre de programmes conçus pour le Big Data font appel aux collections (List, Map, Tuple, Set, Vector, en Java, en Python, et bien sûr en Scala), améliorer leur efficacité est donc crucial.
Or fort à propos, les fonctions d’ordre supérieur nous permettent de manipuler des collections de manière élégante, concise et efficace.
De plus, Scala apporte un niveau d’abstraction supplémentaire lorsqu’il s’agit de parcourir les collections de données ou de les filtrer. L’itération est construite au coeur même des fonctions, ce qui ajoute un niveau d’abstraction supplémentaire et ainsi plus de transparence pour l’utilisateur de la collection qui peut se concentrer sur les besoins fonctionnels et opérationnels et non sur sur les détails d’implémentation technique.
Mais ce n’est pas tout, car nous disposons aujourd’hui y compris sur notre bureau d’ordinateurs ultra performants équipés de plusieurs coeurs. Tirer parti de cette redondance de processeur n’est pas trivial et cela implique que les programmes conçus puissent traiter en parallèle plusieurs tâches.
Vu du développeur, produire du code qui s’exécutera en parallèle sur les ressources disponibles que ce soit sur sa station de travail portable ou sur une grappe de serveurs dans un datacenter d’ Amazon AWS ou de Microsoft AZUR, n’est pas chose aisée surtout lorsqu’il s’agira de synchroniser la bonne exécution des tâches pour fusionner les résultats partiels obtenus sur chacun des noeuds de calcul.
Là aussi, Scala nous apporte un bénéfice sans pareil avec les fonctions d’ordre supérieur, nous confions aux experts les plus capables le soin d’implémenter, une fois pour toutes, une itération parallèle et ensuite nous utilisons des fonctions d’ordre supérieur qui autorisent cette exécution en parallèle pour que l’ensemble de notre projet puisse en bénéficier instantanément.
Si nous résumons à ce stade les bénéfices de Scala:
- Code produit plus lisible, plus facile à expliquer et à documenter
- Code succinct, plus concis plus facile à mettre au point
- Des fonctions d’ordre supérieur qui appliquées aux collections sont très puissantes et épargne beaucoup d’effort d’adaptation du code à notre recherche de solution originale.
- Des abstractions pour mettre en oeuvre du code qui s’exécute en parallèle sur les ressources modernes (multi-coeurs, …), un must pour le Big Data.
Tout cela semble déjà très prometteur mais pourquoi faire appel à Spark?
Spark est aujourd’hui un projet de la fondation Apache. Il fut conçu dès 2009 à l’Université de Berkeley.
Il s’agit d’un ensemble d’outils et de composants logiciels structurés dans un cadre architectural bien défini (Framework) et qui permet de faire du calcul distribué sur nos données Big Data permettant ainsi d’effectuer des analyses complexes à grande échelle.
Il est écrit nativement en Scala, même si, dans son utilisation, il est reste ouvert à Python, R et Java.
Quels sont les bénéfices de Spark pour nous qui cherchons à valoriser nos données d’entreprise?
Spark étant nativement développé en Scala, il profite d’emblée des bénéfices apportés par ce langage de programmation fonctionnelle.
Avec Scala, nous pouvions découper nos données en plusieurs blocs dans la mémoire partagée de notre calculateur puis lancer en parallèle des tâches d’analyse sur plusieurs de ses coeurs de calcul. Avec Spark, nous pouvons maintenant, lancer cette même analyse sur une ferme de plusieurs serveurs(noeuds) eux-mêmes multi-coeurs.
Avec Scala, on peut parler de traitement parallèle sur les données.
Avec Spark, on évoque un traitement des données, parallèle et « distribué ».
Ce modèle est appelé RDD (Resilient Distributed Datasets) dans Spark.
Ces RDD sont des morceaux de nos données Big Data initiales qui se retrouvent en mémoire partagée sur les noeuds de calculs (serveurs) à notre disposition.
Pour l’heure, si nous manipulons nos données Big Data à l’aide de Spark, nos données sont dans des collections distribuées (un ou plusieurs noeuds) et il est important de bien comprendre ce que cela implique quand il s’agira de collecter les résultats de nos manipulations sur le poste de travail de l’analyste.
A l’inverse d’autres solutions Big Data (comme Hadoop par exemple), Spark exécute la totalité de ses tâches en mémoire (in-memory/shared memory) ce qui permet de réduire la latence entre certains traitement sur les collections de données et offre aux analystes une approche itérative en quasi temps réel. C’est pour cela que l’on trouve parfois des rapports de 1 à 100 dans les performances comparatives entre Spark et Hadoop.
Retenons simplement que Spark permet de contourner les effets de la latence du réseau entre le poste de travail de l’analyste et la ferme de calcul ( un des inconvénients majeurs qui impacte un système de traitement par batch à grande échelle comme Hadoop). En effet, il faut avoir conscience que le temps d’accès à une donnée via le réseau internet peut-être jusqu’à 1 million de fois plus long que celui d’un accès en mémoire (in-memory).
Enfin, en complément de la brève introduction aux RDD que nous venons de voir, Spark introduit également d’autres capacités comme:
- des chaines d’opérations de type ETL (Extract-Transform-Load)
- de riches bibliothèques pour des tâches de type « Analytics »
- des librairies de Machine Learning
- des traitements de type Graph processing
Tout cela disponible sur des données statiques (batch processing) ou en flux (streaming processing), sans compter la richesse des API disponibles en Scala, mais aussi python, java, R et SQL.
En conclusion.
Scala et Spark fonctionnent main dans la main et se complètent.
Spark apporte la dimension de distribution de données de très grand volume sur plusieurs noeuds de calcul.
Scala et Spark apportent de grands bénéfices pour la conception d’applications Big Data:
- Code produit plus lisible, plus facile à expliquer et à documenter
- Code succinct, facile à mettre au point
- Des fonctions d’ordre supérieur qui appliquées aux collections et aux RDD sont très puissantes
- Gestion du parallèlisme par les tâches et par les données transparent pour le concepteur d’une application ou d’un traitement ad-hoc
- Traitements par itérations quasi temps réel, gràce à une utilisation extensive de la mémoire cache
- Résilience aux pannes (réseau, noeuds, mémoire) en rejouant les chaines de traitements sur les RDD