Zum Inhalt springen
DedicatedPHP Kontakt

Wenn ein PHP-Prozess nur teilweise abgeschlossen wird: Kompensationen entwerfen

Erfahre, wie du fehlgeschlagene PHP-Abläufe zwischen Systemen wiederherstellst: wann du es erneut versuchst, wann du kompensierst und wie du Ergebnisse protokollierst und Ausnahmen eskalierst.

Redaktionelles Diagramm eines PHP-Prozesses mit Schritten zwischen einer lokalen Datenbank und einer externen API, einschließlich Wiederholungsversuchen und Kompensationen

Ein Geschäftsprozess kann einen Teil seiner Arbeit abschließen und scheitern, bevor er beendet ist. Beispielsweise erstellt eine PHP-Anwendung ein Konto in ihrer Datenbank, kann es aber nicht bei einem externen Dienst provisionieren. Den Ablauf in diesem Moment einfach zu wiederholen, kann Effekte duplizieren; ihn als fehlgeschlagen zu behandeln, kann zu inkonsistenten Systemen führen. Kompensationen in verteilten PHP-Prozessen ermöglichen es, festzulegen, wie auf solche Teilergebnisse reagiert wird, ohne davon auszugehen, dass mehrere Systeme an einer einzigen atomaren Transaktion beteiligt sind.

Die entscheidende Frage ist nicht nur, wie sich bereits Geschehenes rückgängig machen lässt. Manche Effekte können nicht exakt rückgängig gemacht werden, und auch eine Kompensation kann scheitern. Das Design muss den tatsächlichen Status der Operation sichtbar machen, ihre Wiederherstellung ermöglichen und kenntlich machen, wann menschliches Eingreifen erforderlich ist.

Lokale Transaktionen, Wiederholungsversuche und Kompensationen lösen unterschiedliche Probleme

Lokale Transaktionen, Wiederholungsversuche und Kompensationen lösen unterschiedliche Probleme — guía visual de DedicatedPHP

Eine Datenbanktransaktion schützt Änderungen innerhalb der Grenzen dieser Datenbank. Speichert der Prozess mehrere Zeilen und schlägt eine Operation vor dem COMMIT fehl, kann er ein ROLLBACK ausführen, um diese Änderungen zu verwerfen. Dieses Rollback zieht jedoch keine versendete E-Mail zurück, storniert nicht automatisch eine bereits von einer API angenommene Anfrage und macht keine bestätigten Änderungen in einer anderen Datenbank rückgängig.

Bei einem Wiederholungsversuch wird eine Aktion erneut ausgeführt, die möglicherweise aufgrund eines vorübergehenden Problems wie eines Timeouts oder einer Nichtverfügbarkeit fehlgeschlagen ist. Das ist nur dann sinnvoll, wenn die Folgen einer Wiederholung bekannt sind. Die Anfrage könnte das externe System erreicht haben, obwohl die Antwort verloren ging; ohne einen Idempotenzschlüssel oder eine Statusabfrage könnte der erneute Versuch ein Duplikat erzeugen.

Eine Kompensation führt eine Geschäftsaktion aus, die einem bereits abgeschlossenen Schritt entgegenwirkt: zum Beispiel einen gerade angelegten Zugang zu deaktivieren. Sie ist kein technisches Rollback und garantiert nicht, dass der vorherige Zustand exakt wiederhergestellt wird. Bei einem Abgleich hingegen werden die lokal protokollierten Daten mit dem Zustand der beteiligten Systeme verglichen, um Abweichungen zu erkennen und zu beheben. Ein Abgleich kann auch dann erforderlich sein, wenn Wiederholungsversuche und Kompensationen vorhanden sind.

Modelliere jede Operation als Abfolge beobachtbarer Schritte

Beschreibe den Ablauf als einzelne Schritte, bevor du Ausnahmebehandlungsroutinen schreibst. Gib für jeden Schritt an, welches System er verändert, welches Ergebnis als Erfolg gilt, wie die Operation identifiziert wird, ob eine Wiederholung sicher ist und welche Alternative besteht, wenn der Schritt nicht abgeschlossen werden kann. Lege außerdem fest, welche Effekte konsistent bleiben müssen; diese Geschäftsregel ist die Invariante, an der sich die Wiederherstellung orientiert.

Speichere in der Anwendung einen Datensatz zur Operation und ihren Schritten. Ein einfaches Modell kann eine stabile Operations-ID, den Gesamtstatus, den Schrittnamen, das Ergebnis, die Anzahl der Versuche, Zeitstempel und den letzten relevanten Fehler enthalten. Statuswerte wie ausstehend, in Bearbeitung, abgeschlossen, fehlgeschlagen, wird kompensiert und Überprüfung erforderlich helfen dabei, zwischen bekannten und noch nicht bestätigten Sachverhalten zu unterscheiden.

Speichere die lokale Änderung und den Arbeitsauftrag atomar, wenn sie miteinander verknüpft bleiben müssen. Eine Warteschlange kann anschließend den externen Aufruf verarbeiten; das Outbox-Muster ist eine Möglichkeit zu verhindern, dass eine Datenbankänderung bestätigt wird, während die Benachrichtigung verloren geht, die den nächsten Schritt auslösen sollte. Es beseitigt keine Netzwerkausfälle: Der Verbraucher muss weiterhin wiederholte Nachrichten und ungewisse Ergebnisse tolerieren.

Halte eine Datenbanktransaktion nicht während eines Netzwerkaufrufs offen. Externe Aufrufe haben Latenz und können blockieren, während die verlängerte Transaktion Ressourcen bindet und die beiden Systeme nicht atomar macht. Bestätige die lokale Arbeit nach einer expliziten Abfolge und protokolliere, was für die Fortsetzung oder Kompensation erforderlich ist.

Entwirf explizite, begrenzte und idempotente Kompensationen

Entscheide für jeden Schritt, der einen Effekt erzeugt, ob es eine Kompensation gibt und wann sie ausgeführt werden soll. Die Kompensation muss nicht die wörtliche Umkehrung sein. Hat ein Konto bereits eine Benachrichtigung erhalten, lässt sich nicht rückgängig machen, dass die Nachricht gelesen wurde; gegebenenfalls muss eine Korrektur protokolliert oder über die Stornierung informiert werden. Ist eine Aktion unumkehrbar oder hat sie rechtliche oder finanzielle Folgen, kann es richtig sein, den Ablauf anzuhalten und zu eskalieren.

  • Idempotenz: Die zweimalige Ausführung derselben Kompensation darf keine zusätzlichen Effekte erzeugen. Verwende, sofern das System dies unterstützt, eine stabile Operations-ID oder einen Idempotenzschlüssel und protokolliere das Ergebnis.
  • Reihenfolge: Lege fest, welche Schritte kompensiert werden und in welcher Reihenfolge. Üblicherweise wird versucht, die Schritte in umgekehrter Ausführungsreihenfolge rückgängig zu machen; Abhängigkeiten und Geschäftsregeln können jedoch eine andere Reihenfolge erfordern.
  • Grenzen: Lege fest, bei welchen Fehlern Wiederholungsversuche zulässig sind, wie viele Versuche unternommen werden und wann Schluss ist. Plane Wartezeiten zwischen den Versuchen ein und vermeide unbegrenzte Wiederholungen.
  • Ungewissheit: Läuft eine API-Anfrage in ein Timeout, frage ihren Status ab oder verwende einen Idempotenzschlüssel, bevor du eine Erstellung wiederholst oder eine möglicherweise falsche Kompensation ausführst.

Die Kompensationslogik sollte eine klar identifizierbare Geschäftsoperation sein und kein allgemeiner Block, der beim Abfangen jeder beliebigen Ausnahme Daten löscht. Bewahre den erforderlichen Verlauf auf, um zu erklären, was geschehen ist, und zu prüfen, ob die Reaktion den Produktregeln entspricht.

Hypothetisches Beispiel: Ein Konto in zwei Systemen anlegen

Angenommen, ein Ablauf erstellt ein lokales Konto und fordert einen externen Anbieter auf, einen Arbeitsbereich zu aktivieren. Die Anwendung weist eine Operations-ID zu und erfasst die Kontoerstellung als ausstehend. In einer lokalen Transaktion speichert sie das Konto und einen Auftrag zur Anforderung der Bereitstellung. Ein PHP-Worker verarbeitet den Auftrag und protokolliert die externe ID sowie das Ergebnis der Anfrage.

Bestätigt der Anbieter die Aktivierung, setzt der Ablauf die Operation auf abgeschlossen. Antwortet er mit einem bekannten vorübergehenden Fehler, kann der Auftrag mit begrenzter Anzahl von Versuchen und demselben Idempotenzschlüssel erneut ausgeführt werden. Ist die Antwort ungewiss, versucht die Anwendung zunächst herauszufinden, ob der Arbeitsbereich existiert. Bestätigt der Anbieter die Erstellung, verhindert aber eine spätere lokale Voraussetzung den Abschluss der Kontoerstellung, kann das System als Kompensation die Deaktivierung des Arbeitsbereichs anfordern und das Ergebnis speichern.

Schlägt die Deaktivierung fehl, darf die Kontoerstellung nicht als rückgängig gemacht gelten. Die Operation bleibt in einem sichtbaren Status wie „Wiederherstellung ausstehend“ oder „Überprüfung erforderlich“, zusammen mit der lokalen und externen ID, den Versuchen und dem Fehler. Das Betriebsteam benötigt ein Verfahren, um den Anbieter zu überprüfen, die zulässige Aktion festzulegen und das Ergebnis zu protokollieren. Das Beispiel ist hypothetisch: Die konkreten Aktionen hängen von den Fähigkeiten der API und den Geschäftsregeln ab.

Wenn auch die Kompensation scheitert: Transparenz und Überprüfung

Ein verteilter Ablauf kann nicht garantieren, dass jede Aktion automatisch rückgängig gemacht wird. Entwirf einen expliziten Ausweg für ausgeschöpfte Wiederholungsversuche, eine mehrdeutige externe Antwort oder das Scheitern der Kompensation. Bewahre den Status, ohne die Inkonsistenz zu verschleiern, und stelle die Operation dem Benutzer nicht als abgeschlossen dar, solange sie es noch nicht ist.

Stelle dem Support oder Betrieb eine Ansicht bereit, die den Status jedes Schritts, den letzten Fehler, Korrelations-IDs und zulässige Aktionen anzeigt. Die menschliche Überprüfung muss durch Zugriffskontrollen geschützt sein und eine auditierbare Aufzeichnung der Entscheidung hinterlassen. Stelle Metriken und Warnmeldungen bereit, um festgefahrene Operationen, fehlgeschlagene Kompensationen und Abweichungen zu erkennen, die länger als betrieblich akzeptabel bestehen. Ein regelmäßiger Abgleich kann lokale Datensätze mit dem externen System vergleichen und Fälle zur Klärung von Abweichungen eröffnen.

Teste Teilausfälle und entscheide, ob du eine Kompensation brauchst

Teste Teilausfälle und entscheide, ob du eine Kompensation brauchst — guía visual de DedicatedPHP

Tests müssen mehr als nur den Erfolgsfall abdecken. Simuliere Fehler vor und nach jedem Effekt, verspätete Antworten, Timeouts mit unbekanntem Ergebnis, doppelte Nachrichten, unterbrochene Prozesse und Fehler während einer Kompensation. Überprüfe den nach einem Neustart des Workers gespeicherten Status und stelle sicher, dass Wiederholungsversuche keine Konten oder andere Operationen duplizieren.

  • Bleiben die Operations-ID und die Ergebnisse der einzelnen Schritte erhalten?
  • Erzeugt eine wiederholte Nachricht dasselbe Ergebnis ohne doppelte Effekte?
  • Wird der externe Status abgefragt, wenn die Antwort auf eine Anfrage ungewiss ist?
  • Wird die Kompensation in der vorgesehenen Reihenfolge ausgeführt und ist sie bei Wiederholung sicher?
  • Bleibt die Operation bei einem Fehler der Kompensation sichtbar und wird sie zur Überprüfung weitergeleitet?
  • Lässt sich der lokale Status später mit dem externen System abgleichen?
  • Prüfen die Tests die Geschäftsregeln, nicht nur die Antwortcodes?

Wirkt sich der Ablauf nur auf ein einziges System aus und schützt eine lokale Transaktion alle Änderungen, können diese Transaktion und eine einfache Wiederherstellung ausreichen. Gibt es wiederholbare externe Effekte mit bekannten Garantien, genügen möglicherweise idempotente Wiederholungsversuche und ein Abgleich. Muss einem bestätigten Schritt entgegengewirkt werden, um eine Geschäftsregel einzuhalten, definiere eine Kompensation. Die zusätzliche Komplexität lohnt sich, wenn die Kosten unentdeckter Teilzustände höher sind als die Kosten für die Pflege von Protokollierung, Tests und Betriebsverfahren.

Möchten Sie diese Ideen in Ihrem Projekt anwenden?Lass uns über deine PHP-Plattform sprechen.
Verwandten Dienst anzeigen