- Authors

- Name
- Phillip Pham
- @ddppham
TL;DR
- Saga Pattern ersetzt verteilte Two-Phase-Commits durch eine Kette lokaler Transaktionen mit definierten Kompensations-Aktionen bei Fehlern
- Choreography laesst Services selbststaendig auf Events reagieren -- einfach bei wenigen Services, schwer nachvollziehbar bei komplexen Ablaeufen
- Orchestration nutzt einen zentralen Saga-Koordinator, der den Ablauf steuert -- besser fuer komplexe Workflows mit vielen Schritten
- Jeder Schritt braucht eine Kompensation: Bestellung stornieren, Zahlung zurueckbuchen, Reservierung aufheben -- diese muessen idempotent sein
- Auf Kubernetes lassen sich Sagas mit Event-Brokern (Kafka), Workflow-Engines (Temporal) oder Dapr Building Blocks umsetzen
Kubernetes Saga Pattern: Verteilte Transaktionen fuer Microservices
In einer monolithischen Anwendung laeuft eine Bestellung in einer einzigen Datenbank-Transaktion: Bestellung anlegen, Zahlung buchen, Versand ausloesen -- alles atomar, alles konsistent. Schlaegt ein Schritt fehl, macht ein Rollback alles rueckgaengig.
In einer Microservices-Architektur auf Kubernetes hat jeder Service seine eigene Datenbank. Ein Two-Phase-Commit ueber Service-Grenzen hinweg ist in der Praxis nicht tragbar: Er blockiert Ressourcen, skaliert nicht und fuehrt bei Netzwerkpartitionen zu undefinierten Zustaenden.
Das Saga Pattern loest dieses Problem durch eine Sequenz lokaler Transaktionen. Jeder Service fuehrt seine lokale Transaktion aus und publiziert ein Event. Bei einem Fehler werden bereits abgeschlossene Schritte durch Kompensations-Aktionen rueckgaengig gemacht.
Wer die Grundlagen von Microservices-Kommunikation auf Kubernetes vertiefen will: Kubernetes Dapr: Sidecar-Pattern fuer Microservices.
Das Problem: Verteilte Transaktionen
Bestellvorgang (3 Services, 3 Datenbanken):
1. Order Service */} Bestellung anlegen (orders-db)
2. Payment Service */} Zahlung buchen (payments-db)
3. Shipping Service */} Versand beauftragen (shipping-db)
Ohne Saga: Schlaegt der Shipping Service fehl, bleiben Bestellung und Zahlung bestehen. Der Kunde wurde belastet, erhaelt aber keine Ware. Mit Saga: Der Fehler loest Kompensationen aus -- Payment bucht zurueck, Order storniert. Das System kehrt in einen konsistenten Zustand zurueck.
Variante 1: Choreography-basierte Saga
Bei der Choreography reagiert jeder Service eigenstaendig auf Events. Es gibt keinen zentralen Koordinator.
Fehlerfall mit Kompensation
Order Service Payment Service Shipping Service
| | |
|-- OrderCreated --*/}| |
| |-- PaymentCompleted ->|
| | |-- ShippingFailed!
| |<- CompensatePayment -|
|<- CompensateOrder --| |
| | |
(Order storniert) (Zahlung zurueckgebucht) |
Order Service Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: shop
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
saga-role: participant
spec:
containers:
- name: order-service
image: registry.example.com/order-service:v2.4.0
ports:
- containerPort: 8080
env:
- name: KAFKA_BROKERS
value: "kafka-0.kafka.shop.svc.cluster.local:9092"
- name: KAFKA_TOPIC_ORDERS
value: "saga.orders"
- name: KAFKA_CONSUMER_GROUP
value: "order-service-saga"
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
readinessProbe:
httpGet:
path: /healthz/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
Fuer Health Checks und Probes in der Praxis: Kubernetes Health Checks und Probes.
Choreography: Vor- und Nachteile
| Aspekt | Bewertung |
|---|---|
| Entkopplung | Hoch -- Services kennen nur Events, nicht andere Services |
| Einfachheit | Gut bei 2-4 Services, schlecht bei 5+ |
| Nachvollziehbarkeit | Schwierig -- verteilte Logik, kein zentraler Ueberblick |
| Fehlerbehandlung | Jeder Service muss Kompensation selbst implementieren |
Variante 2: Orchestration-basierte Saga
Ein zentraler Saga Orchestrator steuert den Ablauf. Er ruft Services in der definierten Reihenfolge auf und loest bei Fehlern die Kompensationen in umgekehrter Reihenfolge aus.
Ablauf mit Orchestrator
Saga Orchestrator
|
|--1. CreateOrder -------*/} Order Service
|<--- OrderCreated ---------|
|
|--2. ProcessPayment ----*/} Payment Service
|<--- PaymentCompleted ------|
|
|--3. ArrangeShipping ---*/} Shipping Service
|<--- ShippingFailed! ------|
|
|--4. CompensatePayment -*/} Payment Service (Kompensation)
|--5. CompensateOrder ---*/} Order Service (Kompensation)
|
Saga Status: COMPENSATED
Saga Orchestrator Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: saga-orchestrator
namespace: shop
spec:
replicas: 2
selector:
matchLabels:
app: saga-orchestrator
template:
metadata:
labels:
app: saga-orchestrator
spec:
containers:
- name: orchestrator
image: registry.example.com/saga-orchestrator:v1.2.0
ports:
- containerPort: 8080
env:
- name: KAFKA_BROKERS
value: "kafka-0.kafka.shop.svc.cluster.local:9092"
- name: SAGA_STATE_STORE
value: "redis-master.shop.svc.cluster.local:6379"
- name: SAGA_TIMEOUT_SECONDS
value: "30"
- name: SAGA_RETRY_MAX
value: "3"
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
Saga Definition als ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: order-saga-definition
namespace: shop
data:
order-saga.yaml: |
saga: order-processing
version: v1
steps:
- name: create-order
service: order-service
action: /api/orders
compensation: /api/orders/{orderId}/cancel
timeout: 10s
- name: process-payment
service: payment-service
action: /api/payments
compensation: /api/payments/{paymentId}/refund
timeout: 15s
- name: arrange-shipping
service: shipping-service
action: /api/shipments
compensation: /api/shipments/{shipmentId}/cancel
timeout: 10s
on_failure: compensate_all
on_timeout: compensate_all
Kompensations-Logik: Die Rueckwaerts-Kette
Kompensationen sind das Herzstrueck jeder Saga. Sie muessen drei Eigenschaften erfuellen:
1. Idempotenz
Eine Kompensation darf mehrfach ausgefuehrt werden und muss immer das gleiche Ergebnis liefern. Bei Netzwerk-Timeouts wird die Kompensation erneut gesendet. Der Payment Service prueft vor jedem Refund, ob die Zahlung bereits zurueckgebucht wurde.
2. Retries mit Backoff
apiVersion: v1
kind: ConfigMap
metadata:
name: saga-retry-config
namespace: shop
data:
retry-policy.yaml: |
compensation:
max_retries: 5
initial_delay: 1s
max_delay: 30s
backoff_multiplier: 2
retryable_errors:
- TIMEOUT
- SERVICE_UNAVAILABLE
non_retryable_errors:
- INVALID_REQUEST
- NOT_FOUND
3. Saga-Status Tracking
Jede Saga durchlaeuft definierte Zustaende: STARTED, STEP_PENDING, STEP_COMPLETED, COMPENSATING, COMPENSATED, COMPLETED oder FAILED. Der Status wird im Redis State Store persistiert und ist jederzeit abfragbar.
Choreography vs. Orchestration: Entscheidungsmatrix
| Kriterium | Choreography | Orchestration |
|---|---|---|
| Anzahl Services | 2-4 Services optimal | 5+ Services optimal |
| Team-Struktur | Autonome Teams | Zentrales Platform-Team |
| Aenderungshaeufigkeit | Selten neue Schritte | Haeufig neue Schritte |
| Debugging | Distributed Tracing noetig | Zentrales Saga-Log |
| Latenz | Niedriger (kein Hop ueber Orchestrator) | Hoeher (zusaetzlicher Hop) |
| Verfuegbarkeit | Kein Single Point of Failure | Orchestrator muss HA sein |
Fuer die Wahl der richtigen Deployment-Strategie der Saga-Services: Kubernetes Deployment Strategien.
Monitoring und Observability
Saga-spezifische Metriken
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: saga-orchestrator-monitor
namespace: shop
spec:
selector:
matchLabels:
app: saga-orchestrator
endpoints:
- port: metrics
interval: 15s
path: /metrics
| Metrik | Beschreibung | Alert-Schwelle |
|---|---|---|
| saga_total | Gesamtzahl gestarteter Sagas | Baseline |
| saga_compensated | Sagas mit Kompensation | Rate ueber 5% |
| saga_failed | Fehlgeschlagene Sagas (inkl. Kompensation) | Jeder Einzelfall |
| saga_duration_seconds | Dauer einer Saga End-to-End | p99 ueber 30s |
Saga Pattern mit Temporal auf Kubernetes
Temporal ist eine Workflow-Engine, die Saga-Orchestration nativ unterstuetzt. Workflows sind als Code definiert, Retries und Kompensationen sind eingebaut.
apiVersion: apps/v1
kind: Deployment
metadata:
name: temporal-worker
namespace: shop
spec:
replicas: 3
selector:
matchLabels:
app: temporal-worker
template:
metadata:
labels:
app: temporal-worker
spec:
containers:
- name: worker
image: registry.example.com/saga-worker:v1.0.0
env:
- name: TEMPORAL_HOST
value: "temporal-frontend.temporal.svc.cluster.local:7233"
- name: TEMPORAL_NAMESPACE
value: "shop-sagas"
- name: TEMPORAL_TASK_QUEUE
value: "order-saga-queue"
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
Temporal bietet gegenueber einer Eigenentwicklung: automatische Retries, Saga-Kompensation als Workflow-Primitive, Visibility API fuer den Status aller laufenden Sagas, und Versioning fuer Workflow-Updates ohne Downtime.
Fuer event-basierte Skalierung der Saga-Teilnehmer: Kubernetes KEDA Autoscaling.
Best Practices
- Kompensationen immer idempotent implementieren: Netzwerk-Fehler fuehren zu Retries. Eine doppelt ausgefuehrte Kompensation darf keine Seiteneffekte haben.
- Timeouts definieren: Jeder Saga-Schritt braucht ein Timeout. Ohne Timeout haengen Sagas ewig im Status STEP_PENDING.
- Dead Letter Queues einrichten: Events, die nach allen Retries nicht verarbeitet werden koennen, landen in einer DLQ fuer manuelle Analyse.
- Saga-ID durch alle Services propagieren: Eine eindeutige Saga-ID erleichtert Tracing und Debugging ueber Service-Grenzen hinweg.
- Events versionieren: Schema-Aenderungen an Saga-Events muessen rueckwaertskompatibel sein.
Verwandte Artikel
- Kubernetes Dapr: Sidecar-Pattern fuer Microservices
- Kubernetes KEDA: Event-driven Autoscaling
- Kubernetes Deployment Strategien
- Kubernetes Backup und Disaster Recovery
- Kubernetes Health Checks und Probes
Sie implementieren verteilte Transaktionen in Ihrer Microservices-Architektur oder planen die Migration von einem Monolithen? Wir unterstuetzen Sie bei der Wahl des richtigen Saga-Patterns, der Kompensations-Logik und dem produktiven Betrieb auf Kubernetes. Kontaktieren Sie uns unter /kontakt.
Kubernetes-Beratung gesucht?
Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
KEDA Autoscaling: Event-driven Skalierung einrichten
KEDA einrichten für Event-driven Autoscaling mit Kafka, RabbitMQ und Azure Queue inklusive Scale-to-Zero und Kostenoptimierung in Kubernetes.
Kubernetes Integration Patterns: API Gateway, Mesh, Events
Die drei zentralen Integration Patterns für Kubernetes-Microservices: API Gateway, Service Mesh und Event-Driven Architecture im Praxisvergleich.
Kubernetes CQRS Pattern Microservices in Deutschland optimal nutzen
Optimieren Sie Skalierbarkeit und Performance Ihrer komplexen Microservices auf Kubernetes in Deutschland mit dem CQRS Pattern. Erfahren Sie, wie diese zukunftsweisende Architektur Compliance-Anforderungen erfüllt und digitale Souveränität für deutsche Unternehmen sichert.
Kubernetes Deutschland: Knative Serverless & Event-driven Functions
Optimieren Sie Ihre IT mit Knative Serverless auf Kubernetes Deutschland. Erfahren Sie, wie Scale-to-zero und Event-driven Functions Kosten senken, die Entwicklung beschleunigen und Ihre DevOps-Teams im deutschen Mittelstand stärken, mit voller Datensouveränität.
Distributed Tracing: Jaeger auf Kubernetes einrichten
Jaeger für Distributed Tracing auf Kubernetes einrichten mit dem Jaeger Operator. OpenTelemetry-Instrumentation in Go und Python, Trace-Propagation zwischen Microservices und praktische Analyse von Latenz-Problemen.