Indførelse af hændelsesdreven arkitektur til ordrebehandling
Kontekst
Vores synkrone pipeline til ordrebehandling var ved at blive en flaskehals. Langvarige operationer blokerede checkout-flowet, og fejl i efterfølgende services forårsagede kaskadeeffekter.
Beslutning
Migrere ordrebehandlingen til en hændelsesdreven arkitektur med Apache Kafka
Overvejede alternativer
Optimere det eksisterende synkrone flow
- Ingen arkitekturændringer nødvendige
- Teamet er allerede fortrolig med kodebasen
- Lavere risiko
- Løser ikke det grundlæggende koblingsproblem
- Stadig sårbar over for fejl i efterfølgende services
- Begrænsede skalerbarhedsforbedringer
Bruge en simpel message queue (RabbitMQ/SQS)
- Enklere end Kafka
- Lettere at drifte
- Godt nok til grundlæggende asynkron behandling
- Ingen mulighed for at afspille hændelser igen
- Begrænset opbevaring
- Sværere at tilføje nye consumers senere
Bruge Kafka til event streaming
- Genafspilning af hændelser til fejlfinding og gendannelse
- Nemt at tilføje nye consumers
- Høj gennemstrømning og holdbarhed
- Naturlig audit-log
- Driftsmæssig kompleksitet
- Indlæringskurve for teamet
- Udfordringer med eventual consistency
Begrundelse
Kafkas event log-model giver de muligheder, vi får brug for, efterhånden som vi vokser: genafspilning til fejlfinding, nem tilføjelse af nye consumers og et naturligt audit-spor. Den driftsmæssige kompleksitet kan håndteres med moderne værktøjer, og teamet er klar til at højne deres kompetencer inden for distribuerede systemer.
Vendepunktet
Vores checkout-flow gjorde for meget synkront:
- Validere lagerbeholdning
- Behandle betaling
- Opdatere lagerbeholdning
- Sende bekræftelsesmail
- Underrette lageret
- Opdatere analytics
Hvis ét trin fejlede eller var langsomt, mislykkedes hele checkouten. På Black Friday medførte betalingsudbyderens latenstid en checkout-fejlrate på 30 %.
Hændelsesdrevet design
Vi omdesignede systemet omkring hændelser:
Ordre afgivet → [Kafka] → Flere consumers
├── Inventory Service
├── Payment Service
├── Notification Service
├── Warehouse Service
└── Analytics Service
Hver consumer behandler uafhængigt. Fejl er isolerede og forsøges igen uden at påvirke brugeren.
Udfordringer ved implementeringen
Eventual consistency: Brugere kunne se “ordre afgivet”, før lagerbeholdningen var opdateret. Vi tilføjede optimistiske UI-opdateringer og tydelige statusindikatorer.
Idempotens: Consumers skal kunne håndtere duplikerede hændelser. Vi implementerede idempotensnøgler for alle operationer.
Overvågning: Distribueret tracing blev afgørende. Vi investerede kraftigt i observability.
Resultater
- Checkout-succesrate: 99,7 % (op fra 94 %)
- Gennemsnitlig checkout-tid: 800 ms (ned fra 3,2 s)
- Black Friday blev håndteret med 3x den tidligere spidsbelastning uden problemer
- Nye funktioner (svindeldetektion, loyalitetspoint) blev tilføjet uden at røre checkout-koden
Migreringen tog 4 måneder, men forbedrede grundlæggende systemets modstandsdygtighed.