Ana içeriğe geç
Blog'a Dön
MicroservicesDistributed SystemsArchitecturePatterns
Ağaç (Tamamlanmış)

Mikroservislerde Veri Tutarlılığı: CAP Teoremi ve Saga Pattern

2025-11-0512 dk

Mikroservis mimarisine geçiş yapan ekiplerin duvara tosladığı ilk konu genellikle "transaction yönetimi" olur. Monolitik dünyada @Transactional anotasyonuyla çözdüğümüz o konforlu, atomik işlemler, dağıtık dünyada tam bir baş ağrısına dönüşür. Bir sabah uyanırsınız ve sipariş servisinde "ödendi" görünen bir işlemin, ödeme servisinde "başarısız" olduğunu fark edersiniz. İşte o an, dağıtık sistemlerin acımasız gerçeğiyle yüzleşirsiniz.

CAP Teoremi: İmkansız Üçlüyle Dans

Eric Brewer'ın CAP teoremi, dağıtık sistemler üzerine çalışan herkesin başucunda durması gereken bir gerçekliktir. Teorem bize şunu söyler: Bir dağıtık sistemde şu üç özellikten sadece ikisini aynı anda garanti edebilirsiniz:

  1. Consistency (Tutarlılık): Her okuma işlemi en son yazılan veriyi veya hatayı döner. Yani sistemin neresine sorarsanız sorun, aynı cevabı alırsınız.
  2. Availability (Erişilebilirlik): Her istek (hata içermeyen) mutlaka bir yanıt alır. Sistem asla "şu an meşgulüm" demez.
  3. Partition Tolerance (Bölünme Toleransı): Ağ kopukluklarına, mesaj kayıplarına rağmen sistem çalışmaya devam eder.

Gerçek dünyada ağ problemleri kaçınılmazdır (P). Kablolar kopar, switch'ler yanar, latency artar. Dolayısıyla P'den vazgeçme lüksümüz yoktur. Seçiminiz C ve A arasındadır. Mikroservisler genellikle AP (Availability + Partition Tolerance) tarafını seçer. Yani, "sistem her zaman cevap versin ama veriler bir süre tutarsız olabilir" deriz. İşte buna "Eventual Consistency" (Nihai Tutarlılık) diyoruz.

Two-Phase Commit (2PC): Neden Kaçınmalıyız?

Eskiden dağıtık transaction'lar için 2PC (Two-Phase Commit) protokolü kullanılırdı. Mantığı bir düğün törenine benzer. Bir koordinatör (nikah memuru), tüm servislere (gelin ve damat) "Hazır mısınız?" diye sorar. Hepsi "Evet" derse "Commit" emri verilir. Biri bile "Hayır" derse veya cevap vermezse, işlem iptal edilir.

Ancak bu yöntem modern, yüksek trafikli sistemlerde bir darboğazdır:

  • Blocking: En yavaş servisi beklersiniz. Ödeme servisi yavaşsa, tüm sipariş süreci yavaşlar.
  • Single Point of Failure: Koordinatör çökerse sistem kilitlenir. Kimse ne yapacağını bilemez.
  • Scalability: Ölçeklenmesi zordur. Binlerce işlemde bu kilitler sistemi boğar.

Bu yüzden modern mimarilerde 2PC yerine Saga Pattern tercih edilir.

Saga Pattern: Adım Adım İlerlemek

Saga, uzun süren bir işlemi birden fazla küçük, yerel transaction'a böler. Her servis kendi veritabanında işlemini yapar ve bir sonraki adımı tetikleyen bir event fırlatır. Bu, bir bayrak yarışına benzer.

Peki, yarışın ortasında biri düşerse ne olur? Geriye dönüp "Rollback" yapamayız çünkü önceki işlemler commit edildi bile. Bunun yerine "Compensating Transaction" (Telafi Edici İşlem) çalıştırırız. Yani yaptığımızı geri alırız.

Örnek: Bir E-Ticaret Sipariş Süreci

Diyelim ki bir kullanıcı sipariş verdi. Süreç şöyle işler:

  1. Sipariş Servisi: Siparişi "PENDING" olarak kaydeder ve OrderCreated eventini fırlatır.
  2. Stok Servisi: Bu eventi dinler, stoğu düşer ve StockReserved eventini fırlatır.
  3. Ödeme Servisi: Bu eventi dinler, müşterinin kartından parayı çekmeye çalışır.

Senaryo 1: Her Şey Yolunda Ödeme başarılı olur, PaymentSucceeded eventi fırlatılır. Sipariş servisi bunu duyar ve siparişi "COMPLETED" yapar. Mutlu son.

Senaryo 2: Hata! Yetersiz Bakiye Ödeme servisi parayı çekemez ve PaymentFailed eventini fırlatır. İşte Saga'nın telafi mekanizması burada devreye girer:

  1. Stok Servisi: PaymentFailed eventini dinler. Daha önce düştüğü stoğu iade eder (Compensating Transaction).
  2. Sipariş Servisi: PaymentFailed eventini dinler ve siparişi "CANCELLED" olarak günceller.

Sonuçta sistem tutarlı bir hale gelir: Sipariş iptal edilmiş, stok geri konmuş, para çekilmemiştir.

Choreography vs Orchestration

Saga'yı uygulamanın iki ana yolu vardır ve hangisini seçeceğiniz, ekibinizin yapısına ve işin karmaşıklığına bağlıdır.

1. Choreography (Koreografi)

Burada merkezi bir yönetici yoktur. Servisler dansçılar gibidir; müziği (eventleri) dinler ve ne yapacaklarını bilirler.

  • Avantaj: Basit başlar, loose coupling (gevşek bağlılık) sağlar. Servisler birbirini bilmez.
  • Dezavantaj: Süreç karmaşıklaştıkça takip etmek zorlaşır. Kimin hangi eventi dinlediğini, bir hata olduğunda kimin ne yapacağını anlamak için tüm sistemi taramanız gerekir. "Distributed Spaghetti" olma riski vardır.

2. Orchestration (Orkestrasyon)

Burada bir orkestra şefi (Orchestrator) vardır. Genellikle Camunda, Temporal veya Zeebe gibi bir workflow engine kullanılır. Şef, servislere "sen stoğu düş", "sen parayı çek" diye emir verir.

  • Avantaj: Süreç merkezi olarak izlenebilir. Karmaşık akışlar, zaman aşımı (timeout) durumları kolayca yönetilir.
  • Dezavantaj: Orchestrator bir darboğaz olabilir ve servisler şefe bağımlı hale gelebilir.

Sonuç: Mükemmel Diye Bir Şey Yoktur

Mikroservislerde veri tutarlılığı, teknik bir sorundan çok bir iş kuralı tasarımıdır. "Her şey aynı anda tutarlı olsun" ısrarından vazgeçip, "işler yolunda gitmezse nasıl telafi ederiz" sorusuna odaklanmak gerekir.

Saga pattern, eventual consistency'yi yönetmek için güçlü bir araçtır ama bedava değildir. Karmaşıklığı artırır, hata ayıklamayı zorlaştırır. Ancak dağıtık bir dünyada ölçeklenebilir ve dayanıklı sistemler kurmak istiyorsak, bu karmaşıklığı kucaklamak zorundayız. Unutmayın, dağıtık sistemlerde huzur yoktur, sadece yönetilebilir kaos vardır.

Bağlantı Haritası

Mühendislik
Tarih
Anlatılar
Graph Loading...