Playbook
Retry-Algorithmen für Payment-Worker (Retry Algorithmen Fuer Payment Worker)
Exponential Backoff, Jitter, Caps, der Unterschied zwischen Retry und Defer sowie Circuit Breaker — die Taxonomie aus dem vorherigen Teil wird zu…
Verteilte Payment Engine (Distributed Payment Engine)
Teil 12 von 22
Serie zur verteilten Payment-Architektur — die Lücke zwischen Capture und Complete.
Im vorherigen Teil haben wir vier Fehlerkategorien definiert. Dieser Teil baut den eigentlichen Algorithmus für die drei Kategorien, die für Retry geeignet sind (Timeout nach Statusabfrage, Rate Limited, Infrastructure): Wie lange warten wir, wie oft versuchen wir es, und wann stoppen wir ganz und öffnen einen Circuit Breaker?
Versuch 1 → fehlgeschlagen → warten (Backoff) → Versuch 2
→ fehlgeschlagen → länger warten → Versuch 3
→ fehlgeschlagen → Cap erreicht → Defer / Dead-Letter
Zwei Begriffe sollten hier nicht verwechselt werden: Retry bedeutet, im selben Worker fast sofort erneut zu versuchen; Defer bedeutet, den Job zurückzulegen und viel später erneut aufzugreifen. Beides sieht wie 'noch einmal versuchen' aus, aber Timing und Verantwortung unterscheiden sich.
Wo die Begriffe zuerst auftauchen
📦 Exponential Backoff
Eine Strategie, die die Wartezeit bei jedem Versuch verdoppelt: base * 2^attempt.
📦 Jitter
Ein zufälliger Versatz auf die Backoff-Wartezeit, der verhindert, dass viele Worker im exakt gleichen Moment erneut versuchen (Thundering Herd).
📦 Cap
Eine Obergrenze für Wartezeit und/oder Versuchsanzahl, die eine endlose Retry-Schleife verhindert.
📦 Circuit Breaker
Ein Schutzmechanismus, der Anfragen vollständig stoppt, sobald eine Abhängigkeit dauerhaft fehlschlägt, und sie später erneut testet.
Backoff ohne Jitter bedeutet, dass Hunderte im selben Moment fehlgeschlagene Jobs exakt zur selben Millisekunde erneut versuchen — und einen bereits belasteten PSP noch weiter belasten.
Die Backoff-Formel — und warum eine feste Wartezeit nicht reicht
Eine feste Wartezeit von einer Sekunde ist einfach, hat aber zwei Probleme: Erlebt der PSP nur eine kurze Spitze, reicht eine Sekunde vielleicht nicht; hat sich der PSP schon erholt, ist eine Sekunde unnötige Verzögerung. Exponential Backoff beginnt schnell und wird mit jedem Versuch vorsichtiger:
delay = min(cap, base * 2^attempt) + random(0, jitterRange)
Versuch 0 → ~200ms
Versuch 1 → ~400ms
Versuch 2 → ~800ms
Versuch 3 → ~1600ms
...
Versuch N → erreicht den Cap (z. B. 30s)
Ohne Jitter ist diese Formel gefährlich: Alle Worker, die zur gleichen Zeit fehlgeschlagen sind, versuchen exakt nach 200ms, 400ms, 800ms erneut und treffen den PSP in synchronisierten Wellen. Ein zufälliger Zusatz (Full Jitter oder Decorrelated Jitter) verteilt diese Welle.
Der Unterschied zwischen Retry und Defer
Retry bedeutet: derselbe Worker, im selben Prozess, versucht dieselbe Anfrage nach kurzer Wartezeit erneut — meist innerhalb von Sekunden. Defer bedeutet: der Job wird zurück in die Datenbank oder Queue gelegt und erst viel später erneut aufgegriffen — Minuten, manchmal Stunden. Ein Rate-Limited-Fehler wird meist mit Retry gelöst; erlebt der PSP selbst einen großflächigen Ausfall, verbraucht ein minutenlanges Verbleiben in der Retry-Schleife Worker-Kapazität und Ressourcen — Defer ist dann die gesündere Art, den Job für eine Weile 'schlafen zu legen'.
Rate Limited → Retry (Sekunden, mit Backoff)
Längerer PSP-Ausfall → Defer (Minuten, separater geplanter erneuter Versuch)
Circuit Breaker: wann man ganz aufhören sollte
Wenn Anfragen an eine Abhängigkeit wiederholt fehlschlagen, produziert jede neue Anfrage nur ein bereits bekanntes Ergebnis — sie verbraucht Ressourcen und erhöht die Latenz. Ein Circuit Breaker arbeitet mit drei Zuständen:
Closed → Anfragen laufen normal
│ Fehlerschwelle überschritten
▼
Open → Anfragen werden sofort abgelehnt, erreichen den PSP nie
│ Abkühlzeit vorbei
▼
Half-Open → eine begrenzte Anzahl von Testanfragen wird gesendet
├─ erfolgreich → Closed
└─ fehlgeschlagen → Open
Ein Circuit Breaker ersetzt Retry nicht; er ist die Schicht darüber, die früh erkennt, wann Retry zu reiner Verschwendung wird. Solange der Breaker offen ist, sollten Worker Jobs in die Defer-Queue leiten statt vergeblich weiterzuversuchen.
Wie viele Versuche, wie hoch der Cap
Diese Zahlen sollten nicht willkürlich sein; sie sollten proportional zum eigenen SLA des PSP und zum Geschäftswert des Jobs sein. Für eine hochwertige Zahlung können 8-10 Versuche innerhalb eines 5-Minuten-Fensters angemessen sein; für einen niedrig priorisierten Hintergrundjob reichen vielleicht 3.
Häufig verwechselte Unterschiede
❌ Retry = Defer
✓ Retry passiert innerhalb von Sekunden im selben Prozess; Defer hält den Job für Minuten zurück
❌ Jitter ist eine optionale Verfeinerung
✓ Backoff ohne Jitter macht das Thundering-Herd-Risiko real, nicht theoretisch
❌ Ein Circuit Breaker ist eine Alternative zu Retry
✓ Ein Circuit Breaker ist die Schicht, die entscheidet, wann Retry aufhören muss
Full Jitter vs. kein Jitter
| Kriterium | Kein Jitter | Full Jitter |
|---|---|---|
| Risiko synchronisierter Wellen | hoch | niedrig |
| Lastmuster beim PSP | scharfe Spitzen | verteilt |
| Implementierungsaufwand | niedrig | etwas höher |
Checkliste beim Aufbau des Retry-Algorithmus
- Hat die Backoff-Formel einen Cap, oder könnte die Wartezeit theoretisch unbegrenzt wachsen?
- Wird Jitter angewendet, oder versuchen alle Worker exakt zum gleichen Zeitpunkt erneut?
- Wird zwischen Retry (Rate Limited) und Defer (längerer Ausfall) tatsächlich unterschieden?
- Stoppen Worker wirklich, Anfragen an den PSP zu senden, während der Circuit Breaker offen ist?
- Wurden Versuchsanzahl und Gesamtfenster nach dem echten Geschäftswert des Jobs gewählt, oder willkürlich?
- Werden die Übergänge des Breakers (offen/halb offen/geschlossen) als Metrik erfasst?
Was bleiben soll
- Exponential Backoff allein reicht nicht; ohne Jitter erzeugt er synchronisierte Retry-Wellen.
- Retry und Defer sind nicht dasselbe Verb: eines geschieht in Sekunden, das andere in Minuten bis Stunden.
- Ein Circuit Breaker ist keine Alternative zu Retry, sondern die Schicht, die früh erkennt, wann Retry zur Verschwendung wird.
- Versuchsanzahl und Cap sollten bewusst gewählt werden, basierend auf echtem Geschäftswert.
Ein guter Retry-Algorithmus versteckt Fehler nicht — er macht die Kosten des Fehlers kontrollierbar.
Der nächste Teil widmet sich dem Boden, auf dem diese Retries tatsächlich laufen: eine datenbankgestützte Job-Queue mit Leases, die verhindert, dass zwei Worker denselben Job gleichzeitig bearbeiten.
FAQ
Häufige Fragen
Was ist Exponential Backoff?
Eine Strategie, die die Wartezeit bei jedem Versuch verdoppelt: base * 2^attempt.
Was ist Jitter?
Ein zufälliger Versatz auf die Backoff-Wartezeit, der verhindert, dass viele Worker im exakt gleichen Moment erneut versuchen (Thundering Herd).
Stimmt es, dass „Retry = Defer“?
Retry passiert innerhalb von Sekunden im selben Prozess; Defer hält den Job für Minuten zurück
Was legt dieser Teil fest?
Zwei Begriffe sollten hier nicht verwechselt werden: **Retry** bedeutet, im selben Worker fast sofort erneut zu versuchen; **Defer** bedeutet, den Job zurückzulegen und viel später erneut aufzugreifen. Beides sieht wie 'noch einmal versuchen' aus, aber Timing und Verantwortung unterscheiden sich. Exponential Backoff allein reicht nicht; ohne Jitter erzeugt er synchronisierte Retry-Wellen. Im vorherigen Teil haben wir vier Fehlerkategorien definiert. Dieser Teil baut den eigentlichen Algorithmus für die drei Kategorien, die für Retry geeignet sind (Timeout nach Statusabfrage, Rate Limited, Infrastructure): Wie lange warten wir, wie oft versuchen wir es, und wann stoppen wir ganz und öffnen einen Circuit Breaker?
Gelernte Engineering-Prinzipien
- Backoff ohne Jitter erzeugt synchronisierte Fehlerwellen.
- Retry sind Sekunden, Defer sind Minuten bis Stunden — kein gleiches Verb.
- Ein Circuit Breaker erkennt früh, wann Retry zur Verschwendung wird.
Weiterlesen
Weiterlesen
Nachster Teil der Serie
Datenbankgestützte Jobs mit Leases
Einen Lease per Conditional UPDATE erwerben, der Stuck-Watcher, der verwaiste Arbeit rettet, und warum ein Nack des Brokers allein nicht reicht.
Nachster Teil der Serie
Taxonomie der Zahlungsfehler
Ein Timeout, ein 429, ein 5xx, eine Business-Ablehnung und ein Infrastrukturfehler sind nicht dasselbe. Jede Kategorie braucht ihre eigene Retry-Strategie.
Aus derselben Serie
Aufbau eines Zahlungsabgleich-Workers
Wie Sweeper Drift heilen: Der PSP meldet erfolgreich, während der lokale Datensatz abgelaufen ist — und wie gealterte FinalizePending-Einträge aufgelöst…