Asynchrone Jobs ermöglichen die Entkopplung von Importen, Synchronisierungen, Benachrichtigungen, der Dokumenterstellung und Integrationen. Dass ein Consumer eine Nachricht verarbeitet hat, beweist jedoch nicht zwangsläufig, dass das Geschäftsergebnis korrekt ist. Ein Erfolg kann registriert worden sein, bevor ein externer Effekt bestätigt wurde, ein Ausfall kann zwischen zwei Schritten aufgetreten sein oder derselbe Vorgang kann mehr als einmal ausgeführt worden sein.
Der Abgleich asynchroner Jobs in PHP schließt diese Lücke: Er vergleicht, was das System erreichen sollte, mit den Nachweisen darüber, was passiert ist, erkennt fehlende oder abweichende Ergebnisse und löst eine kontrollierte Korrektur aus. Er ersetzt weder Queue, Retries noch Idempotenz; er ergänzt sie durch eine unabhängige Prüfung.
Eine technische Ausführung ist nicht gleichbedeutend mit einem Geschäftsergebnis

Eine Aufgabe kann ohne Exception enden und dennoch einen unvollständigen Prozess hinterlassen. Beispielsweise erstellt eine Anwendung eine Synchronisierungsanfrage, der Consumer ruft eine externe API auf und erhält aufgrund einer Netzwerkunterbrechung eine nicht schlüssige Antwort. Wenn er ohne idempotenten Schlüssel erneut versucht, kann er ein Duplikat erstellen. Wenn er von Erfolg ausgeht, kann der Datensatz unsynchronisiert bleiben.
Auch darf keine bestimmte Zustellsemantik der Messaging-Infrastruktur vorausgesetzt werden. Die Möglichkeit von Redeliveries und doppelten Ausführungen hängt vom Broker, seiner Persistenzkonfiguration, den Bestätigungen, dem Verhalten des Consumers und den auftretenden Fehlern ab. Das Design muss diese Eigenschaften in der gewählten Technologie überprüfen und sie, wenn Duplikate oder Umordnungen auftreten können, ausdrücklich tolerieren.
Die operative Frage lautet nicht nur „Wurde die Nachricht konsumiert?“, sondern „Kann ich nachweisen, dass der erwartete Effekt existiert, gegebenenfalls genau einmal und mit den korrekten Daten?“. Dieser Nachweis erfordert eine Evidenzquelle: eine abfragbare Antwort des externen Systems, eine persistierte Remote-ID, ein gespeichertes Dokument oder eine bestätigte Statusänderung.
Retries, Idempotenz und Abgleich: unterschiedliche Verantwortlichkeiten
Retries behandeln vorübergehende Fehler: temporäre Nichtverfügbarkeit, Nutzungslimits, kurze Sperren oder Netzwerkprobleme. Es empfiehlt sich, eine maximale Anzahl von Versuchen, progressive Verzögerung, Fehlerklassifizierung und ein Ziel für Nachrichten zu definieren, die Aufmerksamkeit benötigen. Unbegrenzte Retries können einen Datenfehler verbergen oder einen externen Vorfall verschärfen.
Idempotenz macht die Wiederholung eines Vorgangs sicher. Sie kann durch eine stabile Operations-ID erreicht werden, die an einen externen Anbieter gesendet wird, durch eine Unique-Constraint in der Datenbank oder durch eine transaktionale Prüfung vor dem Effekt. Sie bedeutet nicht, dass der Effekt eingetreten ist: Sie bedeutet, dass eine Wiederholung ihn nicht vervielfachen sollte.
Der Abgleich sucht nach ausstehenden, unvollständigen oder widersprüchlichen Vorgängen und entscheidet, was mit jedem einzelnen geschehen soll. Er ist besonders notwendig bei externen Effekten, Batch-Prozessen, Aktualisierungen mehrerer Systeme oder Kommunikationen, deren Empfang nicht allein von der sendenden Anwendung nachgewiesen werden kann.
- Verwenden Sie Retries, um als vorübergehend klassifizierte Fehler erneut zu versuchen.
- Verwenden Sie Idempotenz, damit Retries oder Redeliveries keine Effekte duplizieren.
- Verwenden Sie Abgleich, um den Endzustand zu prüfen und erkannte Abweichungen zu beheben.
Den Vorgang modellieren und überprüfbare Evidenz aufbewahren
Ein wartbares Design trennt drei Konzepte. Der angeforderte Job repräsentiert die Absicht, beispielsweise „Bestellung 452 synchronisieren“. Der erwartete Effekt definiert das beobachtbare Ergebnis: „Das externe System enthält die Bestellung mit Version 7“. Die Bestätigung speichert den Nachweis, dass dieses Ergebnis existiert: Remote-ID, Version, Zeitstempel, validierte Antwort oder Ergebnis einer späteren Abfrage.
Erstellen Sie vor dem Veröffentlichen einer Nachricht einen Ausführungsdatensatz in einer dauerhaften Datenbank. Wenn die Anwendung eigene Daten ändert und eine Nachricht veröffentlicht, sollten Sie das Outbox-Pattern in Betracht ziehen: Speichern Sie die Geschäftsänderung und das ausstehende Ereignis in derselben Transaktion und überlassen Sie die Veröffentlichung einem späteren Prozess. Dadurch sinkt das Risiko, die lokale Änderung zu bestätigen und die Nachricht zu verlieren oder eine Nachricht für eine zurückgerollte Änderung zu veröffentlichen.
Der Datensatz sollte mindestens Folgendes enthalten:
- Eine unveränderliche und eindeutige operation_id, die zur Korrelation von Nachrichten, Logs und externen Aufrufen verwendet wird.
- Operationstyp, betroffene Entität sowie Version oder Fingerabdruck des erwarteten Inhalts.
- Aktueller Status, Anzahl der Versuche, nächster zulässiger Versuch und Zeitstempel.
- Idempotenzschlüssel und, falls vorhanden, Kennung der Remote-Ressource.
- Zusammengefasste Evidenz und sichere Verweise auf Antworten oder Fehler, ohne Secrets oder unnötige personenbezogene Daten zu protokollieren.
- Grund für Abschluss, Kompensation, Verwerfung oder Eskalation zur manuellen Prüfung.
Definieren Sie explizite Übergänge, zum Beispiel: pending, processing, awaiting_confirmation, confirmed, retry_scheduled, manual_review, compensated und not_applicable. Jeder Übergang muss einen Verantwortlichen und eine überprüfbare Bedingung haben. Ein bedingtes Update, etwa der Übergang zu processing nur dann, wenn der vorherige Status pending ist, verringert Race Conditions zwischen Consumern.
Den Abgleichsprozess aufbauen
Der Abgleich kann über einen geplanten PHP-Befehl, einen dedizierten Worker oder einen operativen Ablauf ausgeführt werden. Er muss mit Zeitfenstern arbeiten: Untersuchen Sie keine Vorgänge, die vor wenigen Sekunden erstellt wurden, wenn die externe Integration üblicherweise mehrere Minuten benötigt. Definieren Sie das Fenster anhand realer Latenzdaten und überprüfen Sie es bei Änderungen von Limits oder Anbietern.
Vergleichen Sie für jeden geeigneten Vorgang zuvor definierte Quellen der Wahrheit. Die lokale Datenbank kann die maßgebliche Quelle für die Absicht und die Version der Daten sein, das externe System dafür, ob es die Ressource empfangen oder erstellt hat. Wenn keine zuverlässige Abfrage des Ziels existiert, kann die Evidenz eine signierte Empfangsbestätigung, eine Anbieterkennung oder eine zeitversetzte Prüfung anhand einer Ergebnisdatei sein.
- Wählen Sie unbestätigte Vorgänge aus, die ihre erwartete Frist überschritten haben.
- Prüfen Sie mithilfe von
operation_id, Idempotenzschlüssel oder einem eindeutigen Geschäftsschlüssel, ob der Effekt existiert. - Vergleichen Sie relevante Felder und Versionen, nicht nur die Existenz der Ressource.
- Klassifizieren Sie den Fall als fehlend, korrekt, abweichend, mehrdeutig oder nicht anwendbar.
- Führen Sie die autorisierte Aktion aus und speichern Sie die Entscheidung zusammen mit ihrer Evidenz.
Ein mehrdeutiges Ergebnis darf nicht automatisch dazu führen, dass der Vorgang erneut in die Queue gestellt wird. Wenn ein Aufruf eine Ressource erstellt haben könnte, aber keine Möglichkeit besteht, sie zuverlässig abzufragen, könnte ein Retry eine Zahlung, Benachrichtigung oder ein Dokument duplizieren. Sperren Sie in diesen Fällen die automatische Aktion und leiten Sie den Fall mit ausreichendem Kontext an ein Ausnahme-Dashboard weiter, damit eine Entscheidung getroffen werden kann.
Korrigieren, ohne neue Schäden einzuführen
Die Aktion hängt von der Abweichung und den Kosten einer Fehlentscheidung ab. Erneut in die Queue stellen ist geeignet, wenn der Effekt fehlt und der Vorgang idempotent ist. Kompensieren kann einen falschen Effekt durch einen expliziten Geschäftsvorgang rückgängig machen, nicht durch ein pauschales technisches Löschen. Zur Prüfung markieren ist bei Mehrdeutigkeit, Versionskonflikten oder finanziellen Folgen vorzuziehen. Als nicht anwendbar schließen ist sinnvoll, wenn die Entität gemäß dokumentierten Regeln storniert oder ersetzt wurde.
Auch manuelle Reparaturen müssen nachvollziehbar sein: Wer hat die Entscheidung getroffen, welche Evidenz wurde geprüft, welche Aktion wurde angewendet und was war das Ergebnis? Begrenzen Sie Berechtigungen und vermeiden Sie Schaltflächen, die einen Vorgang ausführen, ohne Entität, Version, Ziel und Duplizierungsrisiko anzuzeigen.
Observability und Tests, die das Design validieren
Über operation_id korrelierte Logs erleichtern es, einen Vorgang über Web, Worker und externe Dienste hinweg zu verfolgen. Nützliche Metriken beschränken sich nicht auf Exceptions: Messen Sie das Alter ausstehender Vorgänge, die Anzahl der Vorgänge im Status manueller Prüfung, die Abweichungsrate, Retries nach Ursache und die Zeit bis zur Bestätigung. Alerts sollten bei Anhäufung, Alter oder Fristüberschreitung ausgelöst werden, nicht bei jedem einzelnen Fehler.
Testen Sie repräsentative Fehler: Ausfall nach dem externen Effekt und vor dem Persistieren der Bestätigung; doppelte Ausführung; Nachricht in falscher Reihenfolge; Neustart des Workers; Timeout mit ungewissem Remote-Ergebnis; längere Nichtverfügbarkeit; und Versionsänderungen, während ein Vorgang aussteht. Der Test muss sowohl den Endzustand als auch das Fehlen von Duplikaten und die Qualität der gespeicherten Evidenz prüfen.
Beispiel: Einen Datensatz mit einem externen System synchronisieren
Angenommen, eine PHP-Anwendung synchronisiert einen Kundendatensatz. Bei dessen Änderung erstellt sie den Vorgang sync_customer mit einer stabilen Kennung und der erwarteten lokalen Version. Der Worker sendet diese Werte an das Ziel, wobei die stabile Kennung als Idempotenzschlüssel dient. Erhält er eine gültige Bestätigung, persistiert er die Remote-ID und ändert den Status zu confirmed.
Tritt der Timeout nach dem Senden der Anfrage auf, belässt der Worker den Vorgang in awaiting_confirmation. Der Abgleichsprozess fragt das Ziel anhand des Idempotenzschlüssels ab. Findet er dieselbe Version, bestätigt er. Findet er sie nicht, plant er eine erneute Übermittlung. Findet er eine andere Version, markiert er den Fall zur Prüfung, anstatt Daten zu überschreiben, die im anderen System rechtmäßig geändert worden sein könnten.
Checkliste zur Einführung von Abgleich ohne den Prozess neu zu schreiben

- Erfassen Sie die vorhandenen Jobs und priorisieren Sie jene, die externe Effekte erzeugen, Geld, regulatorische Daten oder schwer wiederholbare Prozesse betreffen.
- Dokumentieren Sie für jeden Typ den erwarteten Effekt, die Quelle der Wahrheit und die Evidenz, die seine Bestätigung ermöglicht.
- Überprüfen Sie bei dem konkreten Broker und den Consumern, was bei Ausfällen, verspäteten Bestätigungen, Persistenz, Redelivery und Nachrichtenreihenfolge geschieht.
- Fügen Sie eine stabile
operation_idhinzu und propagieren Sie sie in Nachricht, Logs, externen Aufrufen und Statusdatensätzen. - Führen Sie eine Vorgangstabelle mit Status, Versuchen, Fristen, Idempotenzschlüssel und Evidenz ein; beginnen Sie bei Bedarf im Beobachtungsmodus.
- Definieren Sie bedingte Übergänge und eine schriftliche Richtlinie zum erneuten Versuchen, Bestätigen, Kompensieren, Eskalieren oder Schließen als nicht anwendbar.
- Implementieren Sie einen Abgleichsprozess, der auf ein Zeitfenster und einen Pilot-Operationstyp begrenzt ist.
- Validieren Sie mit Fällen von Duplikaten, mehrdeutigen Timeouts, Ausfällen zwischen Schritten, Umordnung und Neustart, bevor Sie Korrekturen automatisieren.
- Erstellen Sie ein Ausnahme-Dashboard oder eine Ausnahmeabfrage mit Alter, Entität, Evidenz und empfohlener Aktion.
- Überprüfen Sie regelmäßig Metriken, festgefahrene Vorgänge und manuelle Entscheidungen, um Fristen, Regeln und Kontrollen anzupassen.
Eine schrittweise Einführung ermöglicht es, die Zuverlässigkeit zu verbessern, ohne die gesamte Architektur zu ersetzen: Machen Sie zunächst unsichere Vorgänge sichtbar, bestätigen Sie anschließend Ergebnisse und automatisieren Sie zuletzt nur Korrekturen, deren Sicherheit Sie nachweisen können.



