ServicesÀ proposNotesContact Me contacter →
EN FR
Note

Patterns de retry et de rattrapage pour les pipelines

Comment configurer les retries, le backoff exponentiel et les mécanismes de rattrapage dans les pipelines de données pour que les pannes transitoires se résolvent d'elles-mêmes sans intervention humaine.

Planté
gcpdata engineeringautomation

Une configuration correcte des retries élimine une large part des incidents en production sans nécessiter de détection d’anomalies ni d’outillage IA. Les erreurs réseau transitoires, les limites de débit des API, les brèves pannes en amont et les aléas des services cloud se résolvent d’eux-mêmes si le pipeline attend et recommence.

La combinaison de la logique de retry et des patterns de rattrapage est le fondement de la résilience des pipelines. C’est le niveau 1 et le niveau 2 du spectre de maturité des pipelines auto-guérissants, et c’est là que la plupart des équipes devraient investir en premier.

Configuration des retries

Une bonne stratégie de retry a quatre composants : un nombre de retries, un délai initial, un comportement de backoff et un plafond.

Dans Airflow, des valeurs par défaut raisonnables ressemblent à ceci :

default_args = {
"retries": 3,
"retry_delay": timedelta(minutes=5),
"retry_exponential_backoff": True,
"max_retry_delay": timedelta(minutes=30),
"on_failure_callback": alert_slack,
"sla": timedelta(hours=2),
}

Chaque paramètre a sa raison d’être.

retries: 3 donne au pipeline trois chances après la panne initiale. La plupart des erreurs transitoires se résolvent en un ou deux retries. Aller au-delà de 5 aide rarement et peut retarder la détection de panne si le problème est persistant.

retry_delay avec retry_exponential_backoff empêche le pipeline de marteler un service en difficulté. Le premier retry attend 5 minutes, le deuxième attend 10, le troisième attend 20. Le backoff exponentiel est particulièrement important pour les limites de débit des API, où réessayer immédiatement ne fait qu’étendre la fenêtre de limitation.

max_retry_delay plafonne le backoff pour que le troisième ou quatrième retry n’attende pas des heures. Trente minutes est un plafond raisonnable pour la plupart des pipelines batch. Pour les pipelines quasi-temps-réel, vous abaisseriez cela significativement.

on_failure_callback ne se déclenche qu’après épuisement de tous les retries. C’est le bon endroit pour une alerte Slack, pas après chaque tentative de retry individuelle. La personne d’astreinte devrait être informée des pannes que le pipeline n’a pas pu résoudre seul, pas des aléas transitoires qui se sont résolus au deuxième retry. Voir Patterns de livraison des alertes pipeline pour structurer ces alertes de manière actionnable.

sla fixe une échéance pour la tâche entière. Si la tâche (retries inclus) ne s’est pas terminée dans les 2 heures, cela déclenche une alerte de dépassement SLA. Cela attrape le scénario où les retries réussissent techniquement mais le pipeline est coincé dans une boucle de retry qui va dépasser vos engagements de fraîcheur des données.

Ce que les retries ne gèrent pas

Les retries fonctionnent pour les erreurs transitoires et externes. Ils ne fonctionnent pas pour :

  • Les erreurs logiques dans votre code de transformation. Si votre SQL a un bug, réessayer trois fois produit trois échecs identiques.
  • Les changements de schéma. Si la table en amont a supprimé une colonne, aucun retry ne la ramènera. C’est là que l’adaptation à la dérive de schéma prend le relais.
  • Les problèmes de qualité de données. Si la source envoie des données corrompues ou mal formées, les retries ne font que relire les mêmes données corrompues. C’est là où le pattern Try-Heal-Retry avec diagnostic IA devient pertinent, ou où des couches de validation explicites attrapent le problème.

Cette distinction compte parce qu’elle détermine ce qui se passe après l’épuisement des retries. Une erreur transitoire qui épuise les retries indique probablement une panne plus longue et mérite une alerte. Une erreur persistante qui échoue identiquement à chaque retry nécessite une investigation, pas plus de retries.

Le pattern de rattrapage

Le rattrapage va au-delà des retries. Au lieu de simplement ré-exécuter une tâche en échec, le rattrapage traite les données depuis le dernier point de contrôle réussi jusqu’au moment présent. Si l’exécution de lundi a échoué et celle de mardi réussit, le pattern de rattrapage assure que l’exécution de mardi récupère les données de lundi et de mardi.

Pour les modèles incrémentaux dbt, c’est intégré. La logique is_incremental() compare par rapport au dernier timestamp matérialisé. Si une exécution échoue et que la table n’est pas mise à jour, la clause WHERE de la prochaine exécution réussie capture tout depuis la dernière matérialisation réussie.

{% if is_incremental() %}
WHERE event_timestamp > (SELECT MAX(event_timestamp) FROM {{ this }})
{% endif %}

Si l’exécution de lundi a échoué, MAX(event_timestamp) dans la table cible pointe toujours vers dimanche. L’exécution de mardi récupère les données de lundi et de mardi automatiquement. Pas d’intervention manuelle, pas de lacune dans les données.

Airflow dispose également d’un support natif du rattrapage. Configurer catchup=True sur un DAG signifie que si le DAG a été mis en pause puis repris trois jours plus tard, Airflow planifie des exécutions pour tous les intervalles manqués. Combiné au pattern incrémental dbt, cela crée un double filet de sécurité : l’orchestrateur rattrape les exécutions manquées, et la couche de transformation rattrape les données manquantes.

L’idempotence comme prérequis

Le rattrapage ne fonctionne que si votre pipeline est idempotent : exécuter la même opération deux fois produit le même résultat qu’une seule exécution. Si retraiter une fenêtre temporelle crée des doublons ou double-compte des valeurs, le rattrapage aggrave les choses plutôt que de les améliorer.

Pour dbt, l’idempotence dépend de votre stratégie incrémentale. Une stratégie merge avec une unique_key appropriée est naturellement idempotente parce que les enregistrements en double sont mis à jour plutôt qu’insérés. Une stratégie insert_overwrite est idempotente parce qu’elle remplace des partitions entières. Une stratégie append n’est pas idempotente, et l’utiliser avec une logique de rattrapage crée des doublons.

Le pattern de déduplication explicite dans votre SELECT gère les cas limites :

QUALIFY ROW_NUMBER() OVER (
PARTITION BY event_id
ORDER BY updated_at DESC
) = 1

Cela assure que même si les données source contiennent des doublons ou que le pipeline retraite des fenêtres qui se chevauchent, la sortie reste propre.

Combiner retries et alerting

L’objectif est un pipeline qui gère les pannes courantes silencieusement et alerte sur les rares. Le pattern de configuration :

  1. Les retries gèrent les erreurs transitoires. Trois retries avec backoff exponentiel.
  2. on_failure_callback alerte après épuisement des retries. L’équipe ne voit que les pannes nécessitant une attention humaine.
  3. Le monitoring SLA attrape la dégradation lente. Même si chaque retry individuel réussit, dépasser le délai SLA signale un problème.
  4. Le rattrapage comble les lacunes automatiquement. La prochaine exécution réussie traite les données manquantes sans backfill manuel.

Cette approche à quatre couches gère la majorité des incidents en production pour la plupart des équipes data. Le processus d’astreinte ne s’active que pour les pannes qui survivent à ces quatre couches, ce qui signifie que l’ingénieur d’astreinte traite des problèmes genuinement nouveaux plutôt que des erreurs transitoires routinières.

Là où cette configuration atteint ses limites, ce sont les types de pannes que les retries ne peuvent pas résoudre et que le rattrapage ne peut pas compenser : les formats de fichiers modifiés, les problèmes d’encodage, les nouvelles formes de données que la transformation n’attend pas. C’est le territoire des niveaux supérieurs d’auto-guérison, de l’adaptation à la dérive de schéma jusqu’à la remédiation propulsée par IA.