Aller au contenu

Quiz 09 – Structured Streaming : premiers flux et analyse de logs

  • Jour 3
  • 20 questions
  • Seuil de réussite : 70 %
  • 20 flashcards

Contenus évalués : lecture d'un dossier en continu avec `readStream` et schéma explicite ; écriture avec `writeStream`, `trigger` (`processingTime`, `availableNow`) et `checkpointLocation` ; suivi avec `recentProgress` et `lastProgress` ; reprise après panne et rôle de `--reset` ; jointure flux-statique avec le référentiel des zones ; output modes `append`, `update` et `complete` ; fenêtres temporelles fixes et glissantes sur le temps de l'événement ; watermark, lignes en retard ignorées et compromis réactivité-exhaustivité ; opérations non supportées sur un flux (distinct exact, tri sans agrégation, append sans watermark) ; `stream_simulator.py` et l'arrivée des données fichier par fichier.

Une seule bonne réponse par question. Toutes les valeurs citées sont celles des TP de la formation. Le corrigé détaillé s’affiche après la correction. Ce quiz prépare le QCM de validation des acquis du dernier jour.

Question 1

Dans le TP 9, tu exécutes ce code. Qu'affiche le print ?

schema = spark.read.parquet("data/trips.parquet").schema
courses = (spark.readStream
           .schema(schema)
           .option("maxFilesPerTrigger", 2)
           .json("stream/courses"))
print(courses.isStreaming)
Question 2

Le simulateur stream_simulator.py écrit chaque fichier dans un sous-dossier _tmp, puis le déplace avec os.replace dans stream/courses ou stream/logs. Pourquoi ?

Question 3

Dans le TP 9, zones est lu avec spark.read.csv("data/taxi_zone_lookup.csv", ...) et joint au flux courses pour ajouter la colonne Borough. Quelle affirmation est juste ?

Question 4

Le TP 9 démarre la requête par_borough avec outputMode("complete"). Que reçoit la console à chaque micro-batch ?

Question 5

La requête du TP 10 s'arrête brutalement en pleine matinée. Tu la relances avec le même checkpointLocation (out/checkpoints/tp10), sans rien supprimer. Que se passe-t-il ?

Question 6

Dans le TP 10, le watermark est de 2 minutes sur ts. En milieu de matinée, alors que le watermark a déjà avancé, une ligne de log arrive avec 5 minutes de retard, comme le simulateur en produit. Que devient-elle ?

Question 7

À la fin du TP 10, tu lis out/tp10/par_minute en batch. Les fenêtres de 8h27 à 8h29 n'y figurent pas. La requête a écrit avec ce code :

q = (par_minute.writeStream
     .outputMode("append")
     .format("parquet")
     .option("path", "out/tp10/par_minute")
     .option("checkpointLocation", "out/checkpoints/tp10"))

Quelle est la bonne explication ?

Question 8

Un collègue veut compter en continu le nombre exact d'utilisateurs distincts sur le flux de logs avec count(distinct user). Que lui réponds-tu ?

Question 9

Dans le TP 10, tu veux afficher les logs triés par ts. Tu ajoutes .orderBy("ts") directement sur le flux logs parsé, sans agrégation, puis tu écris en append. Quelle est la bonne approche ?

Question 10

Bonus du TP 9 : après 60 secondes de stream en direct, le calcul en batch sur les mêmes fichiers donne plus de courses que le stream. Le simulateur produit 1 fichier toutes les 2 secondes, la requête traite maxFilesPerTrigger = 2 fichiers par micro-batch de 5 secondes. Quel diagnostic retiens-tu ?

Question 11

Tu lances python scripts/stream_simulator.py courses --all --reset avec les valeurs par défaut (30 fichiers de 500 courses). Puis tu exécutes le corrigé du TP 9 en mode availableNow, avec maxFilesPerTrigger = 2. Que montre q.recentProgress à la fin ?

Question 12

Pour aller plus vite, un participant retire la ligne .schema(schema) de son readStream du TP 9 :

courses = (spark.readStream
           .option("maxFilesPerTrigger", 2)
           .json("stream/courses"))

Que se passe-t-il ?

Question 13

Avec courses --reset, le simulateur vide stream/courses, mais supprime aussi out/checkpoints/tp9 et out/checkpoints/tp11. Pourquoi ?

Question 14

Dans le TP 10, tu oublies le withWatermark et tu démarres cette requête :

sans_wm = (logs
           .groupBy(F.window("ts", "1 minute"), "endpoint")
           .agg(F.count("*").alias("requetes")))
q = (sans_wm.writeStream
     .outputMode("append")
     .format("parquet")
     .option("path", "out/tp10/par_minute")
     .option("checkpointLocation", "out/checkpoints/tp10")
     .start())

Que se passe-t-il ?

Question 15

À l'étape 6 du TP 10, q.lastProgress affiche un watermark 2024-01-15T13:27:55.000Z. Les logs du simulateur sont pourtant datés de la matinée. Comment lis-tu cette valeur ?

Question 16

Après un logs --reset, tu lis le Parquet du TP 10. Une fenêtre qui commence à 7h52 apparaît, alors que l'horloge du simulateur démarre à 8h00. Quelle explication retiens-tu ?

Question 17

Ton équipe veut deux choses : une alerte sur /payment la plus réactive possible, et un bilan exact des erreurs de la matinée, sans ligne perdue. Quelle approche choisis-tu ?

Question 18

Dans le bonus du TP 10, tu remplaces la fenêtre de 1 minute par F.window("ts", "5 minutes", "1 minute"). Quelle affirmation est juste ?

Question 19

Les alertes du TP 10 (taux d'erreur > 10 %) montrent /payment aux minutes 08:22, 08:23, 08:24 et 08:25. Le simulateur indique pourtant une panne « entre 8h22 et 8h26 ». Un collègue s'étonne de ne pas voir 08:26. Quelle est la bonne explication ?

Question 20

Ton voisin a oublié la ligne spark.conf.set("spark.sql.shuffle.partitions", "4") dans le TP 9. Sa requête donne les bons totaux par Borough, mais chaque micro-batch est nettement plus lent que chez toi. Quel diagnostic retiens-tu ?

Cliquez sur une carte pour la retourner. Mélangez-les pour une révision active.

1 / 20

Dépôt des participants : formations2026/formation-spark-ml (branche participants)

Contenu pédagogique © Ambient IT · 140 Avenue Jean Lolive, 93500 Pantin · formation@ambient-it.net · +33 (0)1 48 10 09 46

Organisme de formation enregistré sous le numéro 11 75 54743 75. Cet enregistrement ne vaut pas agrément de l'État.