Spark est aujourd’hui un incontournable en Big Data pour préparer, traiter, agréger et modéliser de la donnée. En effet, ce framework open source est principalement utilisé pour faire du Data Engineering et de la DataScience. Comment l’utiliser pour vos projets Big Data ? Quels sont ses atouts et ses limites ? Réponses dans cet article.
Spark est déjà incontournable dans l’univers Big Data
Hadoop et Map Reduce ont longtemps dominé à l’avènement des projets Big Data. En revanche, les lenteurs et contraintes associées empêchaient de voir réellement toutes les possibilités de tels projets ni de valoriser le fort potentiel des données.
L’arrivée de Spark combiné à Hadoop, a permis d’améliorer l’architecture existante. Ainsi, il est aujourd’hui possible d’utiliser Spark sans Hadoop, de le faire tourner, dans des conteneurs, et de choisir d’autres systèmes de stockage distribués que HDFS (Hadoop Distributed File System). Avec ses nombreuses fonctionnalités et connecteurs, Spark peut communiquer avec tous les principaux outils et services du marché.
Par ailleurs, certains outils comme DataBricks se sont totalement créés à partir de Spark. En Data Science, la plateforme d’analyse des données, Dataiku, utilise également la puissance de Spark, et les ETL Big Data comme Talend proposent aussi d’écrire des jobs Spark. Si autant de grands noms ont choisi d’utiliser Spark dans leurs outils, ce n’est pas sans raison.
Enfin, l’autre force de Spark est d’unifier les traitements batch et streaming. Plus besoin de mettre en place une architecture complexe, avec deux niveaux de maintenance et des doublements de flux. Un même programme Spark peut gérer des calculs ordonnancés et du temps réel très simplement.
Ainsi, Spark est simple, rapide, et efficace ! De nos jours, il n’est plus possible de parler Data sans évoquer Spark. Et si vous n’en êtes pas encore convaincus, je vous invite à lire un de nos précédents articles : « 5 raisons de choisir Spark pour les traitements de vos Big Data ».
Plusieurs langages proposés par Spark
Spark est une librairie compatible avec les langages de développement Java, Scala, Python et R. Spark peut par ailleurs interpréter du code SQL.
Ce panel de langages permet à tous d’accéder à la puissance de Spark en fonction des langages déjà connus. Chaque langage a sa communauté, des usages différents, et des limitations spécifiques en fonction de la philosophie du langage qui peut être incompatible avec certaines fonctionnalités Spark.
Par exemple, les DataSets Spark obligent au typage des données. Un langage non typé comme Python ne peut donc pas les utiliser.
Dans les outils packagés qui utilisent Spark, généralement tous les langages sont proposés afin de ne pas restreindre les utilisateurs. C’est le cas de DataBricks qui propose de faire du Scala, du Python, du R ou du SQL. Java est le plus souvent absent, car le passage de Java à Scala est relativement simple, et Scala est plus adapté que Java (nous verrons plus loin pourquoi).
Ainsi, nous voyons que Spark propose plusieurs langages afin d’élargir son usage. Pour autant, chaque langage a ses avantages et ses inconvénients. Mais y en aurait-il un qui se démarquerait des autres ?
La philosophie de la librairie Spark est issue de la philosophie du langage Scala. Entre les deux outils, la communication est harmonieuse et performante.
Scala + Spark = l’harmonie parfaite
Scala is the new Java
Scala est un langage de programmation récent visant à répondre aux nouvelles contraintes de scalabilité et de distributivité. Son nom signifie d’ailleurs « Scalable Language ».
Ce language multi-paradigmes a été conçu en 2003 à l’Ecole Polytechnique fédérale de Lausanne (EPFL) par le professeur Martin Odersky.
Scala a une syntaxe simple et pratique qui le rend plus rapide à apprendre que Java. Néanmoins, sa maîtrise complète peut être plus longue car il faut comprendre la programmation orientée objet, la programmation fonctionnelle, la récursivité et les traitements ensemblistes.
Ce langage à typage statique est compilé en bytecode Java et se retrouve donc exécutable dans une JVM (Java Virtual Machine). Nous pouvons ainsi nous appuyer facilement sur des librairies Java ou Scala compilées et faire tourner notre programme sur n’importe quel système d’exploitation.
Quels sont les atouts de Scala pour le Big Data ?
Pour traiter un volume important de données, il faut utiliser un langage parfaitement optimisé, rapide et distribuable. Scala répond nativement à ces 3 besoins. La scalabilité et la distributivité font partie intégrante de son ADN. Il n’est pas nécessaire d’ajouter des librairies supplémentaires pour en profiter, ce qui le rend très performant.
Les variables sont typées de manière statique. Par conséquent, les erreurs de type sont identifiées dès la compilation. Ainsi, tout le code généré est déjà prêt et optimisé, et donc plus rapide à exécuter. Sur des volumes très importants, le moindre petit gain de temps répété sur une action simple se cumule vite en minutes, voire en heures gagnées.
Scala encourage également les traitements ensemblistes qui sont distribués et optimisés nativement. Il est en adéquation parfaite avec la philosophie des traitements Big Data.
Un mariage heureux ? Non, mais une histoire de famille tout de même
Si Spark fonctionne si bien pour nos traitements Big Data, ce n’est pas par hasard. Spark est une librairie, et comme toute librairie, elle a dû être développée. A votre avis, quel langage a été utilisé pour la réaliser? Eh oui, Spark a été développé en Scala !
Si développer en Scala + Spark fonctionne si bien, ce n’est donc pas pour rien ! La philosophie de la librairie Spark est issue de la philosophie du langage Scala. Entre les deux outils, la communication est harmonieuse et performante.
Ainsi, toutes les possibilités offertes par Spark sont accessibles en Scala.
Le développement pur pour une maîtrise totale et des performances optimales
Maintenant que vous savez pourquoi je préfère développer en Scala pour Spark, je vais vous expliquer pourquoi je préfère développer directement en Spark+Scala plutôt que d’utiliser un ETL (Extract Transform Load).
La maîtrise
J’aime bien maîtriser totalement ce que je fais. Le NoCode est à la mode, et est souvent très pratique pour rendre accessible au plus grand nombre des outils et fonctionnalités. Avoir une interface visuelle et des blocs à manipuler est bien sûr plus simple à appréhender. Il y a déjà du code pré-écrit et nous pouvons donc produire un premier programme fonctionnel plus rapidement.
Cependant, nous ne maîtrisons pas le code généré par cet outil intermédiaire. Le programme peut donc fonctionner, mais ne pas faire totalement ce que nous pensions car nous ne voyons pas toutes les subtilités, et surtout nous n’avons pas la possibilité de l’optimiser précisément.
Pour comparaison, prenons l’exemple d’un site web construit par un outil (par exemple un CMS). Le code HTML généré fonctionne mais n’est pas toujours optimisé. La page mettra sûrement un peu plus de temps à s’afficher. Et si nous voulons faire du spécifique, il faudra comprendre ce code généré peu adapté à une relecture humaine. Nous ne pourrons pas rajouter une fonctionnalité non prévue par l’outil.
Dans le domaine de la Data, nous voulons traiter un volume très important de données. Maîtriser totalement l’ensemble des traitements et les optimiser au maximum me semble donc indispensable. En développement natif avec Scala, nous sommes au plus proche de la librairie Spark, maîtrisant ainsi totalement le programme généré.
La maintenabilité et l’analyse
Dans tous les projets informatiques nous utilisons un outil de versionning. Ainsi, en écrivant nous-même le code, nous savons exactement ce que nous avons changé d’une version à une autre. Seules les lignes impactées sont modifiées, une rétro-analyse des changements apportés est alors simple.
En utilisant des outils intermédiaires qui vont générer du code pour nous, une petite modification peut impacter une grande partie du code automatiquement généré, sans savoir pour quelle raison. L’analyse des changements est toujours possible, mais bien plus complexe. Comme dans tout domaine, plus il y a d’intermédiaires dans une chaîne, plus il devient compliqué de remonter la chaîne et de la maîtriser de bout en bout.
La liberté
J’aime la liberté offerte par le développement pur. Il suffit d’un éditeur de texte ou d’un IDE (Integrated Development Environment ou, en français « environnement de développement »), d’un outil de versionning et d’un compilateur pour démarrer notre projet. Nous pouvons également partir d’un squelette réutilisable de code et non d’un projet vide, puis enrichir ce squelette avec des fonctions utiles et réutilisables.
Pour aller plus loin, il est même possible de transformer en librairie ces fonctions et de les importer facilement ensuite dans nos projets là où elles sont nécessaires. En termes de délais de mise en œuvre, il n’y a pas plus rapide. Nous pouvons trouver des outils parfaitement exploitables professionnellement dans des versions totalement gratuites. Pas de licence à gérer, ni de délais et de surcoûts associés.
Par ailleurs, nous pouvons travailler sur n’importe quel système d’exploitation, chacun avec son environnement de prédilection, et comme nous utilisons des éditeurs de texte, les outils sont légers, fluides et rapides. Dans le cas de multi-projets, nous sommes en mesure d’ouvrir plusieurs instances de notre IDE, de travailler sur plusieurs projets à la fois, et de passer rapidement de l’un à l’autre.
Le fait d’être sur du code (et donc du texte), permet de se servir facilement de la puissance d’une recherche de mots-clés dans un fichier ou dans un projet, et du rechercher-remplacer.
Ces fonctions simples sont terriblement efficaces pour identifier des champs, fonctions, ou règles de gestion, et pour faire du remplacement massif. En cas d’évolution du nom d’une colonne, nous avons la capacité d’impacter rapidement l’ensemble de notre projet.
Les tests
Le développement pur est parfaitement adapté aux tests automatisés. Depuis des années, les projets Web et les logiciels sont écrits en code avec une logique de tests automatisés des fonctionnalités. Ainsi, appliquer la même logique dans un programme Scala+Spark est tout à fait prévu.
De nombreuses librairies issues historiquement du monde Java sont disponibles pour nous aider dans cette tâche.
Nous pouvons ainsi tester des fonctions simples en comparant un résultat attendu d’une fonction selon des paramètres d’entrées spécifiés, mais comme nous travaillons sur de la donnée métier, avec des règles de gestion technique et fonctionnelle, nous pouvons directement les valider par des tests sur de la donnée.
Définir plusieurs jeux de tests
Ainsi, nous définissons plusieurs jeux de tests pour valider chaque règle de gestion à contrôler dans nos développements de transformation. Des jeux de tests pour nos tables ou fichiers en entrée de notre traitement (JDT Entrants), et des jeux de tests pour les résultats attendus (JDT Sortants attendus).
Nous codons un programme de tests qui va vérifier que notre fonction de traitement Spark+Scala prenant en entrée nos JDT Entrants, va bien nous renvoyer exactement les résultats de notre JDT Sortant attendu. Nous comparons donc le résultat du JDT Sortant réellement du programme avec le JDT Sortant attendu. Si le résultat est identique, alors le test est concluant. Sinon, le test a échoué, nous remontons une erreur.
Notre programme contient ainsi une batterie de tests de ce genre pour chacune de nos étapes de mapping et de transformation de la donnée.
L’ensemble de ces tests sont systématiquement lancés par le développeur pour s’assurer que son nouveau développement respecte les règles de gestion, et que les nouveaux développements n’ont pas engendrés de régression sur d’autres fonctions. Cette solution s’intègre facilement à un processus de CI/CD (Intégration Continue/Livraison et Déploiement Continu) pour exécuter automatiquement les tests avant de valider la génération et le déploiement d’un nouveau package.
Et si vous testiez Spark+Scala pour votre prochain projet Big Data ?
Pour conclure, je suis conquis par l’association Spark-Scala pour nos projets Big Data. La complexité croissante des projets ainsi que le besoin d’agilité nécessite d’effectuer des tests au fil de l’eau, de les automatiser pour identifier rapidement une régression et de pré-valider la majorité des traitements avant les tests d’intégration et la recette métier. Les anomalies tardives s’en retrouvent diminuées puisque les tests nous ont déjà permis d’identifier la quasi-totalité des problèmes.
De plus, nous pouvons avec le développement ajuster nos traitements au plus juste et profiter pleinement de la puissance de notre cluster Big Data.
Nous réalisons de plus en plus de projets Big Data pour nos clients avec du Spark+Scala. Ainsi, nous avons créé un KIt Starter Spark (KISS) pour démarrer nos projets avec une base commune de travail. Nous capitalisons également sur des traitements récurrents afin de les rendre génériques et réutilisables. Nous enrichissons notre KISS régulièrement.
En parallèle, nous avons également travailler sur un outil interne pour accompagner la phase de spécification, la sécuriser, et faciliter le développement des projets Big Data via des contrôles de cohérence et de la génération automatique de structures de tables notamment. Plus en savoir plus sur ce sujet de DataOps, je vous conseille également cet article : Conseils pour spécifier et documenter les données d’un projet Big Data.
Si vous souhaitez en savoir plus sur les possibilités de Spark+Scala ou sur les possibilités d’intégration dans votre système actuel, n’hésitez pas à nous contacter.
👉 Retrouvez toute notre actu en temps réel en nous suivant sur LinkedIn 👈
Votre adresse de messagerie est uniquement utilisée par Business & Decision, responsable de traitement, aux fins de traitement de votre demande et d’envoi de toute communication de Business & Decision en relation avec votre demande uniquement. En savoir plus sur la gestion de vos données et vos droits.