Apache Beam : un model de programmation unifié pour les pipelines de traitement de données

Dans cet article, nous allons passer en revue les concepts, l’histoire et le futur d’Apache Beam, qui pourrait bien devenir le nouveau standard pour la définition des pipelines de traitement de données.

Lors du Dataworks Summit 2018 à Berlin, j’ai assisté à la conférence Present and future of unified, portable and efficient data processing with Apache Beam, présentée par Davor Bonaci, V.P. d’Apache Beam qui travaillait précédemment sur Google Cloud Dataflow. Cette conférence a piqué ma curiosité et m’a conduit à écrire cet article qui est divisé en deux parties :

  • Les concepts sur lesquels s’appuie Apache Beam, qui ont été brièvement exposés au cours de la conférence ;
  • La présentation de Apache Beam lui-même, avec un peu de l’histoire, de l’état actuel, et de l’avenir du projet.

Les concepts sur lesquels s’appuie Apache Beam

Avant de parler de Beam lui-même, explorons les concepts qu’il implémente. Cette introduction est basée sur deux articles écrits par Tyler Akidau (Streaming 101 et Streaming 102), Tech Lead pour le groupe Data Processing Languages & Systems chez Google. Il est l’un des principaux auteurs du papier The Dataflow model sur lequel repose Google Cloud Dataflow, le prédécesseur d’Apache Beam.

Le streaming

Voyons d’abord ce qu’implique le streaming lorsque l’on parle de traitement de données.

Un type de moteur de traitement de données conçu pour des ensembles de données infinis (traduit de l’anglais)

Tyler Akidau

Le streaming peut être caractérisé par :

  • Un dataset non délimité (par opposition aux datasets finis) ;
  • Un traitement des données non borné (dans le temps) ;
  • Des résultats rapides, approximatifs et / ou spéculatifs.

En raison de leurs résultats approximatifs, les systèmes de streaming étaient souvent associés à des systèmes de traitement batch plus performants qui donnaient les résultats corrects. L’architecture Lambda est un bon exemple de cette idée. Elle est composée de deux systèmes :

  • Un système streaming qui fournit des résultats rapides et imprécis ;
  • Un système batch qui fournit les résultats corrects plus tard.

L’architecture Lambda fonctionne bien mais pose un problème de maintenance : vous devez construire, provisionner et maintenir deux versions du pipeline de données et fusionner les résultats.

Pour réduire la complexité de l’architecture, Jay Kreps a fusionné les couches de streaming et de batch pour définir l’architecture Kappa. Cette architecture est constituée d’un seul pipeline appliquant des transformations de données successives et utilise un système de stockage capable à la fois de transmettre et de stocker des données (par exemple Apache Kafka).

Tyler Akidau va encore plus loin en s’interrogeant sur le besoin réel de systèmes de traitement batch tels qu’ils existent aujourd’hui. Pour lui, les systèmes de streaming n’ont besoin que de deux choses pour dépasser le batch :

  1. L’exactitude des résultats, qui est apportée par le traitement exactly-once et donc par un stockage cohérent et partition tolerant (pour être sûr de quelles données ont déjà été traitées) ;
  2. Des outils pour raisonner sur le temps, afin de traiter des données non ordonnées, non finies avec des retards variables.

De nouvelles données arrivent, d’anciennes données peuvent être rétractées ou mises à jour, et tout système que nous construisons devrait être en mesure de faire face à ces faits par lui-même, la notion d’exactitude étant une optimisation pratique plutôt qu’une nécessité sémantique. (traduit de l’anglais)

Tyler Akidau

L’équipe de Tyler Akidau a défini un modèle pour ce type de traitement de données, sur lequel s’appuie Google Cloud Dataflow, ainsi qu’Apache Beam : le Dataflow model.

Vocabulaire

Pour comprendre le Dataflow model, introduisons d’abord quelques mots-clés.

Heure de l’évenement contre heure du traitement

Lorsque nous traitons des données, les deux domaines de temps à prendre en compte sont :

  • L’heure de l’événement (event time), l’heure à laquelle un événement s’est réellement produit ;
  • L’heure du traitement (processing time), l’heure à laquelle l’événement est observé par le système.

Dans la vie réelle, le décalage (skew) entre l’heure de l’événement et l’heure du traitement est très variable (en raison des ressources matérielles, de la logique logicielle, de l’émission des données elle-même) :

Difference between event time and processing time

Fig. 1: Difference entre heure de l’événement et heure du traitement

Les fenêtres

Pour traiter un dataset non délimité, il est nécessaire de le diviser en éléments finis. Ces blocs de données finis sont appelés fenêtres (windows). Les fenêtres sont définies par une longueur et une période:

  • Fenêtres fixes (fixed): la longueur et la période sont fixées et égales ;
  • Fenêtres glissantes (sliding): la longueur et la période sont fixées mais la période peut être inférieure à la longueur (entraînant un chevauchement) ;
  • Sessions: ni la longueur ni la période ne sont fixes. Les fenêtres sont définies par des séquences d’événements séparés par des intervalles d’inactivité.
3 windows types

Fig. 2 : 3 types de fenêtres

Lors de la définition des fenêtres, nous pouvons nous baser :

  • Sur un interval entre deux heures de traitements, comme le font de nombreux systèmes existants, mais certaines données finiront dans les mauvaises fenêtres (en raison du décalage entre l’heure de l’événement et l’heure du traitement) ;
  • Sur un interval entre deux heures d’événements, mais cela n’est pas possible car on ne peut pas savoir si toutes les données qui se sont produites dans une fenêtre temporelle ont été observées.

La watermark

Une watermark relie une heure d’événement E à une heure de traitement P avec l’affirmation : “à l’instant P, toutes les données générées avant E ont été observées”. La watermark dépend de la source des données et nous devons la définir en fonction de notre connaissance des données. Avec Apache Beam, le calcul de la watermark est effectué par le système, et elle est affinée au fur et à mesure que les données sont traitées.

Les déclencheurs (triggers)

Un déclencheur définit quand le résultat doit être matérialisé pour une fenêtre. Si nous définissons plusieurs déclencheurs, nous obtenons plusieurs résultats. Ceux-ci peuvent être spéculatifs s’ils sont calculés avant que toutes les données soient observées.

Le Dataflow model

Le Dataflow model permet de définir des pipelines de données en répondant à 4 questions :

  1. Quels résultats sont calculés ?
  2. , dans l’échelle des heures d’évenements, les résultats sont-ils calculés ?
  3. Quand, en heure de traitement, les résultats sont-ils matérialisés ?
  4. Comment les raffinements de résultats s’appliquent-ils ?

Pour mieux comprendre comment ces questions peuvent être appliquées à un cas d’utilisation réel, je vais utiliser les GIFs d’un exemple fourni sur le site web d’Apache Beam. Tyler Akidau donne un exemple plus complexe qu’il lie au SDK de Google Cloud Dataflow dans son article Streaming 102.

Quels résultats sont calculés ?

Ou : Quelles transformations sont appliquées aux données ?

Disons que nous recevons les scores de différents joueurs et que nous voulons additionner les scores obtenus par chaque utilisateur en un jour. Cela correspond à une seule transformation : une somme par clé (une clé correspondant à un utilisateur). Si nous traitons les données une fois par jour, cela nous donnera quelque chose comme ça :

Summing users' scores

Fig. 3: Somme des scores par utilisateur

Dans cette animation (et toutes les suivantes dans cet article), les données reçues sont représentées par des cercles, des carrés et des losanges, la ligne blanche représente la progression en heure de traitement et les résultats passent au jaune lorsqu’ils sont matérialisés.

Ici, nous traitons toutes les données en même temps et obtenons un résultat unique par utilisateur, ce qui correspond à un traitement batch classique.

Où, dans l’échelle des évenement, les résultats sont-ils calculés ?

Ou : Quelles fenêtres sont utilisées pour séparer les données ?

Disons que nous voulons maintenant la somme des scores de chaque utilisateur pour chaque heure. Pour cela, nous définissons une fenêtre fixe de 1 heure en heure d’événement, et chaque fenêtre nous donnera une somme de scores :

Summing users' scores by hour

Fig. 4: Somme des scores par heure par utilisateur

Nous sommes toujours dans un pipeline de traitement batch parce que nous attendons tous les résultats avant de matérialiser les résultats, mais nous obtenons cependant 3 résultats indépendants.

Quand, en heure de traitement, les résultats sont-ils matérialisés ?

Ou :  Selon quels déclencheurs seront matérialisés les résultats ?

Si nous voulons passer de notre pipeline batch à un pipeline streaming, nous ferons face à un problème abordé plus tôt : nous ne pouvons pas être certains que toutes les données d’une fenêtre ont été observées.

C’est pourquoi nous utiliserons des déclencheurs qui peuvent être basés sur :

  • La progression de  la watermark, pour fournir un résultat qui est certainement le résultat final pour une fenêtre (lorsque la watermark atteint la fin de la fenêtre) ;
  • La progression en heure de traitement, pour fournir des résultats périodiques réguliers (par exemple toutes les 10 minutes) ;
  • Le nombre d’éléments observés, pour fournir des résultats après que N nouveaux éléments ont été observés (par exemple tous les 5 éléments) ;
  • Les “ponctuations”, pour fournir des résultats lorsqu’une caractéristique spéciale est détectée dans un élément (par exemple un élément EOF).

Voici un exemple de déclencheur toutes les 10 minutes en heure de traitement, si un nouvel élément a été observé :

Triggering every 10 min when a new element is observed

Fig. 5 : Déclencheur toutes les 10 min si un nouvel élément est observé

Nous pouvons utiliser plusieurs déclencheurs dans un pipeline de données et définir des déclencheurs composites (basés sur des répétitions, des conjonctions, des séquences d’autres déclencheurs).

Le Dataflow model catégorise les résultats en 3 catégories en rapport avec la watermark :

  • Early, lorsqu’il est matérialisé avant la watermark ;
  • On-time, lorsqu’il est matérialisé très proche de la watermark ;
  • Late, lorsqu’il est matérialisé après la watermark.

Dans l’animation ci-dessous, nous choisissons de déclencher un résultat à chaque nouvel élément observé (la watermark est tracé en vert).

Triggered results vs. watermark

Fig. 6 : Résultats matérialisé et watermark 

Comment les raffinements de résultats s’appliquent-ils ?

Ou : Quel mode d’accumulation est choisi pour les résultats ?

Le Dataflow model propose 3 modes d’accumulation pour les résultats multiples d’une fenêtre :

  • Rejet (discarding) : Le résultat actuel ne prend pas en compte les précédents. Si nous voulons additionner les résultats, nous devons le faire manuellement lorsque nous les consommons.
  • Accumulation (accumulating) : Le résultat actuel accumule tous les précédents. Dans le cas de la somme, le dernier résultat d’une fenêtre sera aussi la somme de tous les résultats.
  • Accumulation et rejet : Le résultat actuel accumule tous les résultats passés, mais une rétraction indépendante est produite pour les résultats passés (“Je t’ai dit que le résultat était X, mais j’avais tort, débarrasse-toi du X que je t’ai dit la dernière fois et remplace-le par Y.”).

C’est tout pour le Dataflow model ! Si l’équipe Dataflow a raison, répondre à ces 4 questions devrait permettre de décrire n’importe quel pipeline de traitement de données, à la fois pour des traitements batch et streaming. Si vous voulez approfondir les concepts théoriques du Dataflow model, je vous invite à lire les articles de Tyler Akidau qui sont très bien écrits (en anglais : Streaming 101 et Streaming 102).

Apache Beam

Apache Beam vise à fournir une norme portable pour l’expression de pipelines de traitement de données robustes […] dans une variété de languages sur une variété de plates-formes. (traduit de l’anglais)

Initié par Google et largement soutenu

Apache Beam a été fondée début 2016 lorsque Google et d’autres partenaires (contributeurs sur Cloud Dataflow) ont pris la décision de transférer les SDKs et runners Google Cloud Dataflow vers l’incubateur Apache Beam. Les raisons derrrière la décision de Google sont bien décrites par Tyler Akidau lui-même dans le post Why Apache Beam.

Beaucoup d’organisations qui soutiennent la légitimité du modèle Beam et contribuent au développement d’Apache Beam sont des leaders du traitement de données comme Talend (article) ou data Artisans (article).

Très rapidement, il nous est apparu que le modèle Dataflow […] est le bon modèle pour le traitement des données en streaming et en batch. […] L’API Flink Datastream […] implémente fidèlement le modèle Beam (traduit de l’anglais)

Kostas Tzoumas, CEO de data Artisans and fondateur d’Apache Flink

Cela donne beaucoup de crédibilité à Apache Beam qui a reçu le titre de “Top-Level Apache Software Foundation Project” le 10 janvier 2017.

Mélanger et associer les SDKs et les runtimes

Près de la moitié de la conférence donnée par Davor Bonaci à Berlin portait en fait sur la vision de Beam : permettre aux développeurs d’exprimer facilement des pipelines de données basés sur le Beam model (= Dataflow model) et de choisir entre :

Voici comment nous écririons le pipeline de données illustré dans la Fig. 6 avec le SDK Java :

Le futur de Beam

Compte tenu de la forte confiance dans le modèle Beam de la part des principaux moteurs de traitement de données, il est probable que de nombreuses extensions à l’écosystème Beam soient développées au cours des prochaines années (langages, runners, DSLs, bibliothèques, bases de données, etc.). Davor Bonaci a fortement encouragé à contribuer à Beam si nous manquons de pièces pour l’intégrer dans notre environnement.

Certains des concepts du modèle Beam ne sont pas encore disponibles avec tous les runners Beam comme nous pouvons le voir dans la matrice des capacités (en particulier pour Spark auquel manque beaucoup de types de déclencheurs). Là encore, l’acceptation croissante du modèle Beam devrait pousser les différents runners à adapter leurs moteurs.

L’équipe et les contributeurs de Beam travaillent également sur l’intégration de nouvelles fonctionnalités telles que :

  • La streaming analytics : analyser et effectuer des actions sur des données en temps réel à l’aide de requêtes continues ;
  • Le Complex Event Processing : identifier des patterns d’événements dans des flux et détecter les patterns importants dans les données pour y réagir. Cette fonctionnalité serait inspirée de la bibliothèque FlinkCEP (JIRA).

Conclusion

Nous avons vu qu’Apache Beam est un projet qui vise à unifier plusieurs moteurs de traitement de données et SDKs autour du Dataflow model, qui offre un moyen d’exprimer facilement tout pipeline de données. Ces caractéristiques font de Beam un projet très ambitieux qui pourrait amener les plus grands acteurs du traitement des données à construire un nouvel écosystème partageant le même langage, ce qui a d’ailleurs déjà commencé.

Sources

Images

Par | 2018-06-07T12:31:01+00:00 May 24th, 2018|Data Engineering, DataWorks Summit 2018, Évènements|1 Comment

À propos de l'auteur :

Stagiaire data engineer chez Adaltas.

Un commentaire

  1. […] Apache Beam : un model de programmation unifié pour les pipelines de traitement de données* Apache Beam est l’implémentation de Google du modèle Dataflow pour l’expression de pipelines de traitement de données robustes dans une variété de langues sur une variété de plates-formes à la fois en batch et en streaming. L’article fait suite à la présentation “Present and future of unified, portable and efficient data processing with Apache Beam” présentée par Davor Bonaci. […]

Laisser un commentaire