Saga Pattern
Önce şunu oku: Monolit mi, mikroservis mi?
30 saniyede özet
Servisler ayrılınca 'hepsi ya da hiçbiri' garantisi kaybolur. Saga işi adım adım yapar; bir adım patlarsa öncekiler silinmez, iptal eden yeni adımlarla telafi edilir, tıpkı tatil rezervasyonunu iptal etmek gibi.
Bir tatil planlıyorsun: uçak, otel ve araba. İkisini ayırdın, üçüncüsü kalmamış. Şimdi ne yapacaksın?
Adım adım oku
- İlk adım başarılı: uçak bileti ayrıldı.
- İkinci adım da başarılı: otel ayrıldı.
- Üçüncü adım başarısız: araba yok. Tek bir transaction olmadığı için her şeyi bir anda geri almak mümkün değil.
- Saga, başarılı olan adımları ters sırayla telafi adımlarıyla iptal eder: önce otel, sonra uçak.
-
Bayt: Monolitte sipariş tek bir transaction'dı: ya hepsi olur, ya hiçbiri.
-
Sen: Peki servislere böldükten sonra?
-
Bayt: Ödeme alındı, kargo patladı. Parayı geri almak için bir geri alma düğmesi yok!
-
Bayt: Tatil planında araba bulamazsan oteli geri almazsın, iptal edersin.
Tek parça bir uygulamada sipariş akışı tek bir sözle korunur: “ya hepsi olur, ya hiçbiri.”
@Transactionalpublic void placeOrder(Order order) { orderRepo.save(order); paymentService.charge(order); // bunlar aynı transaction içinde inventoryService.reserve(order); // biri patlarsa hepsi geri alınır}Servisleri ayırdığın an bu garanti yok olur. Her servisin kendi veritabanı var, tek bir COMMIT yok. Saga bu boşluğu doldurur — ama verdiği şey aynı garanti değildir.
Geri alma yok, iptal var
Saga'nın üçüncü adımı olan kargo başarısız oldu. İlk adımda çekilen ödeme, veritabanından iz bırakmadan geri alınır mı? Cevabı göster
Hayır. Ödeme çoktan commit oldu; ancak yeni bir işlemle, bir iadeyle telafi edilir.
Dağıtık transaction’ı, her biri kendi veritabanına hemen commit eden yerel transaction’lar dizisine böl. Her adımın bir de telafi işlemiÖnceki adımın etkisini iş mantığı seviyesinde geri alan yeni bir işlem. Rollback değildir: ödeme silinmez, iade edilir — tarih korunur.Sözlükte gör → eylemi olsun. Bir adım başarısız olursa, önceki adımların telafileri ters sırada çalıştırılır.
Kafam karıştı, daha basit anlat
Saga’da geri alma yoktur, iptal vardır. Ödemeyi geri almazsın, iade edersin. Ekstrede iki satır görünür: ödeme ve iadesi.
Saga deseni hangi problemi çözer?
Kendin çalıştır
Aşağıda beş adımlı bir sipariş sagaBirden fazla servise yayılan işi yerel transaction'lara bölüp, başarısızlıkta telafi işlemleriyle geri saran desen. Atomiklik vermez, eventual consistency verir.Sözlükte gör →sı var. Hangi adım başarısız olsun kutusundan bir adım seç ve telafi zincirinin ters sırada nasıl geri sardığını izle.
Saga — ileri akış ve telafi zinciri
Tohum 3- Order Sipariş oluşturbekliyor
- Payment Ödemeyi çekbekliyor
- Inventory Stok rezerve etbekliyor
- Notification “Siparişin alındı” e-postası göndergeri alınamaz adımbekliyor
- Shipping Kargo oluşturbekliyor
Şu an ne oldu?
Order: Sipariş oluştur
Koordinatör bu adımı çağırdı ve cevabını bekliyor. Akışın tamamı tek bir yerde tanımlı.
Aklında kalsın: Her adım kendi veritabanına hemen commit eder. Bu yüzden saga ortasında başka bir okuyucu yarım kalmış bir durum görebilir.
Görevler0/3
Geri alınamayan bir adımı telafi etmek zorunda kalaçık
İpucu
Varsayılan senaryoyu sonuna kadar oynat. E-posta gönderildikten sonra bir adım düşerse ne "geri alınır"?
Hiçbir geri alınamaz etki bırakmadan geri saraçık
İpucu
Hatayı e-posta adımından önceye taşı. Asıl ders: geri alınamayan adımları saganın sonuna koy.
Mutlu yolda giden bir sagayı elle düşüraçık
İpucu
Başarısız adımı "Hiçbiri" yap, oynat ve akış ortadayken "Şu anki adımı düşür"e bas. Gerçek hatalar senaryoya uymaz.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
Mutlaka dene:
Shippingadımını düşür (varsayılan). Telafiler ters sırada geçiyor, ama “siparişin alındı” e-postası zaten gitmişti.Orderadımını düşür. Geri alınacak bir şey yok; ilk adımın başarısızlığı en ucuzudur.Notificationadımını düşür. E-posta gitmediği için uyarı da yok: adım sırası bir tasarım kararıdır.- Koordinasyon stilini değiştir. Adımlar aynı, akışı bilen değişiyor.
Simülatörün altındaki Görevler listesi bunları hedefe çeviriyor. Sonuncusu senaryonun dışına çıkıyor, çünkü gerçek hatalar önceden seçtiğin adımda gelmez.
Kafam karıştı, daha basit anlat
Bir adım başarısız olunca, o ana kadar tamamlanmış adımlar ters sırayla iptal edilir. En son yapılan iş ilk geri alınır.
Telafi işlemi (compensating transaction) nedir?
Orchestration mı, choreography mi?
| Orchestration | Choreography | |
|---|---|---|
| Akış nerede tanımlı | Tek bir koordinatörde | Hiçbir yerde — olay zincirinden türer |
| Yeni adım eklemek | Koordinatörü değiştir | Yeni servis, yeni olay aboneliği |
| Hata ayıklama | Koordinatörün log’unu oku | Dağıtık trace şart |
| Bağlılık | Koordinatör herkesi tanır | Servisler yalnızca olayları tanır |
| Risk | Koordinatör tek hata noktası | Döngüsel olay zincirleri, görünmez akış |
Pratik kural: adım sayısı üçü geçiyorsa orchestration. Choreography az sayıda adımda zarif, çok sayıda adımda kimsenin tamamını anlayamadığı bir olay çorbasına dönüşür.
Kafam karıştı, daha basit anlat
Orchestration, adımları yöneten bir orkestra şefidir. Choreography’de ise şef yoktur, herkes bir öncekinin bitirdiğini duyunca kendi işine başlar.
Orkestrasyon (orchestration) ile koreografi (choreography) arasındaki temel fark nedir?
Saga’nın vermediği şey: yalıtım
ACID’in dört harfinden saga yalnızca birini gerçekten kaybettirir ama o bir tanesi çok şey ifade eder.
Sipariş oluşturuldu, ödeme çekildi, stok rezervasyonu henüz yapılmadı. Bu anda başka bir istek gelip siparişi okursa yarım kalmış bir durum görür. Veritabanı seviyesinde bunu engelleyen bir kilit yok.
Kullanılan çareler:
- Semantik kilit. Siparişe
PENDINGkoy; okuyanlar geçici olduğunu bilsin. - Değişmez alan (commutative update).
set balance = 100yerinebalance = balance - 20. - Kötümser görünüm. En kötü durumu göster: “işleminiz onaylanıyor”.
Adım sırası bir tasarım kararıdır. Adımları rastgele sıralamazsın. İki kural:
- Geri alınabilir adımlar önce, geri alınamazlar sonra. Simülatör bildirimi kasten kargodan önce koyuyor; doğrusu onu en sona taşımaktı.
- En çok başarısız olan adım başta. Ödeme reddini dördüncü sıraya koyarsan her reddedilen kartta üç telafi çalışır.
Her adımı, telafi edilebilir olup olmadığına göre ayır.
Telafi işleminin kendisi başarısız olursa ne yaparsın?
Tuzaklar: kaçınılmaz iki ayrıntı
Idempotency: telafi çağrısı da ağ üzerinden gider ve başarısız olabilir, dolayısıyla tekrar denenir. “Ödemeyi iade et” iki kez çalışırsa iki kez iade yapmamalı. Her adım ve her telafi bir idempotency anahtarı taşır.
@Transactionalpublic void refund(RefundCommand command) { if (refundRepo.existsByIdempotencyKey(command.key())) { return; // bu iade zaten işlendi, sessizce çık }
var refund = paymentGateway.refund(command.paymentId(), command.amount()); refundRepo.save(new Refund(command.key(), refund.id()));}Outbox: commit edip sonra olay yayınlamak iki ayrı işlemdir; arada düşersen saga asılı kalır. Olayı aynı transaction’da bir outbox tablosuna yaz, ayrı bir süreç broker’a bassın.
Aşağıdaki örnek bir bankadan: vadesiz hesaptan kredi kartı borcu ödemek iki servise ve iki veritabanına yayılır. Orkestrasyonlu saga ile durum veritabanında, her adımın bir telafisi var, cevaplar mesajla geliyor ve cevap gelmeyen adımlar zaman aşımıyla telafi ediliyor.
Derinleş · Kredi kartı borcu ödeme sagası: orkestrasyon, telafi ve zaman aşımı 5 dosya · ~157 satır · ilk okumada atlayabilirsin
Kendini sına
Servisler ayrılınca tek bir veritabanı transaction'ı artık hepsini kapsayamaz.
Aşağıdaki ifadeleri doğru kutuya yerleştir.
Aklında kalacak üç şey
- 1 Telafi işlemi geri almak değildir: geri almak izi siler, telafi yeni bir kayıt yazar. Ödeme iadesi hesap dökümünde ayrı bir satırdır.
- 2 İki stil var: orchestration'da akış tek yerden yönetilir ama o yönetici tek hata noktasıdır; choreography'de kimse akışın tamamını bilmez, hata ayıklamak zorlaşır.
- 3 Saga yalıtım vermez. İş yarıdayken başka biri yarım kalmış durumu görebilir; bunu iş tarafının kabul etmesi gerekir.
5 kart sonraki derste seni bekliyor
Bu dersin üstüne kurulanlar
Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.