Dağıtık Sistemler & Veri Tutarlılığı 7 dk okuma 3 okunma

Eventual Consistency ve CAP Teoremi

CAP teoremi, dağıtık sistemlerde Tutarlılık (Consistency), Erişilebilirlik (Availability) ve Bölünme Toleransı (Partition Tolerance) üçlüsünden en fazla ikisinin aynı anda sağlanabileceğini söyler. Eventual Consistency (Nihai Tutarlılık) ise yüksek erişilebilirlik için tutarlılıktan geçici olarak feragat eden bir modeldir. Bu yazıda, CAP, PACELC, ACID vs BASE ve .NET uygulamaları ele alınır.

Eventual Consistency ve CAP Teoremi

Eventual Consistency ve CAP Teoremi

Dağıtık sistemlerin en temel ikilemi, tutarlılık (consistency) ile erişilebilirlik (availability) arasındaki dengedir. Bir banka hesabından para transferi yaparken tutarlılık hayatidir; ancak bir sosyal medya akışını görüntülerken, birkaç saniyelik gecikme kabul edilebilir. İşte CAP Teoremi ve Eventual Consistency (Nihai Tutarlılık), bu dengeyi anlamanın ve doğru mimari kararlar almanın anahtarıdır.


1. CAP Teoremi Nedir?

CAP Teoremi, Eric Brewer tarafından 2000 yılında öne sürülen ve 2002'de formalize edilen bir teoremdir. Teorem, bir dağıtık sistemin aşağıdaki üç özellikten en fazla ikisini aynı anda garanti edebileceğini söyler:

Özellik Açıklama
Consistency (Tutarlılık) Her okuma, en son yazılan veriyi veya bir hatayı döner. Tüm düğümler aynı veriyi görür.
Availability (Erişilebilirlik) Her istek, başarılı veya başarısız bir yanıt alır (sistem her zaman yanıt verir).
Partition Tolerance (Bölünme Toleransı) Düğümler arasındaki ağ bölünmelerine rağmen sistem çalışmaya devam eder.

Kritik Nokta: Dağıtık sistemlerde Partition Tolerance (P) kaçınılmazdır. Ağ bölünmeleri her zaman olabilir. Bu nedenle gerçek seçim, C ile A arasındadır.

Brewer'ın Kendi Düzeltmesi (2012):

"CAP'teki '2'sini seç' yaklaşımı yanıltıcıdır. Bölünme olmadığında, C ve A birlikte çalışır. Bölünme olduğunda ise seçim yapılır."


2. CAP Sınıflandırması: CP vs AP

A. CP Sistemleri (Tutarlılık + Bölünme Toleransı)

Bölünme durumunda tutarlılığı korur, ancak erişilebilirliği feda eder. Bazı istekler başarısız olabilir veya bloke olabilir.

Örnek Sistemler:

  • ZooKeeper: Lider seçimi (ZAB protokolü); çoğunluk olmadan yazma kabul edilmez.

  • etcd: Kubernetes'in durum deposu; Raft konsensüsü.

  • HBase: Güçlü tutarlılık, tek bölge.

  • MongoDB (majority write concern): Çoğunluk onayı olmadan yazma başarılı sayılmaz.

  • Google Spanner: TrueTime API ile küresel tutarlılık.

Kullanım Alanı:

  • Finansal işlemler (banka transferi)

  • Envanter yönetimi (stok kontrolü)

  • Kimlik doğrulama ve yetkilendirme

  • Rezervasyon sistemleri

B. AP Sistemleri (Erişilebilirlik + Bölünme Toleransı)

Bölünme durumunda erişilebilirliği korur, ancak tutarlılığı feda eder. Tüm düğümler yanıt verir, ancak veriler geçici olarak farklı olabilir.

Örnek Sistemler:

  • Cassandra: LWW (Last-Write-Wins) çakışma çözümü.

  • DynamoDB: Eventual consistent reads (varsayılan).

  • Riak: Vector clocks ile çakışma tespiti.

  • CouchDB: Multi-master replikasyon.

  • Redis Cluster: Asenkron replikasyon.

Kullanım Alanı:

  • Sosyal medya akışları

  • Ürün katalogları

  • Kullanıcı profilleri

  • IoT sensör verileri

  • Analytics ve log toplama


3. Eventual Consistency (Nihai Tutarlılık)

Tanım: Bir veri öğesine yeni bir güncelleme yapılmadığı sürece, sonunda tüm erişimler en son güncellenen değeri döndürür. Yani sistem, belirli bir süre sonra tutarlı hale gelir.

Örnek:

text

1. Kullanıcı profilini günceller (Node A)
2. Node B henüz güncellemeyi almamıştır (eski veriyi döner)
3. Birkaç milisaniye/saniye sonra Node B güncellemeyi alır (yeni veriyi döner)

Eventual Consistency Türleri:

Tür Açıklama
Read-Your-Writes Kullanıcı, kendi yazdığını hemen okur.
Monotonic Reads Kullanıcı, bir kez gördüğü veriyi tekrar gördüğünde daha eski bir sürümü görmez.
Monotonic Writes Bir kullanıcının yazma işlemleri, yapıldığı sırayla uygulanır.
Writes-Follow-Reads Bir okumadan sonra yapılan yazma, o okumanın gördüğü veriye dayanır.

4. ACID vs. BASE

Eventual Consistency, BASE modelinin bir parçasıdır. Klasik ACID ile karşılaştırma:

Özellik ACID (RDBMS) BASE (NoSQL / Dağıtık)
Atomicity Tüm işlem ya başarılı ya başarısız Alt işlemler bağımsız başarılı olabilir
Consistency Her işlem tutarlı bir duruma geçer Geçici tutarsızlık kabul edilir
Isolation Eşzamanlı işlemler birbirini etkilemez Kısmi izolasyon; çakışma olabilir
Durability İşlem sonrası veri kalıcıdır Genelde kalıcı, ancak bölünmede kaybolabilir
Felsefe "Önce doğru, sonra hızlı" "Önce çalışır, sonra doğru"
Kullanım Bankacılık, finans Sosyal medya, e-ticaret katalog, IoT

BASE'in Açılımı:

  • Basically Available: Sistem her zaman erişilebilir (tüm düğümler yanıt verir).

  • Soft State: Sistem durumu zamanla değişebilir (kilit gerekmez).

  • Eventual Consistency: Sistem sonunda tutarlı hale gelir.


5. PACELC Teoremi (CAP'in Uzantısı)

CAP, yalnızca bölünme (partition) durumundaki seçimi açıklar. Ancak bölünme olmadığında da bir seçim vardır: Latency (Gecikme) ile Consistency (Tutarlılık) arasında.

PACELC:

  • Partition varsa: Availability vs Consistency

  • Else (bölünme yoksa): Latency vs Consistency

Sistem Bölünmede Normalde
DynamoDB PA EL (düşük gecikme)
Cassandra PA EL
MongoDB PC EC (güçlü tutarlılık)
HBase PC EC
Cosmos DB PA/PC (seçilebilir) EL/EC
Spanner PC EC

Yorum: Spanner, hem bölünmede hem normal durumda tutarlılığı seçer; bu da yüksek gecikme pahasına küresel tutarlılık sağlar.


6. Çakışma Çözümü (Conflict Resolution)

Eventual Consistency, çakışmaların nasıl çözüleceğini tanımlamalıdır.

A. Last-Write-Wins (LWW)
En son yazan kazanır (zaman damgasına göre). Basit ama veri kaybına yol açabilir.

csharp

// Cassandra'da LWW
// Yazma 1: 10:00:00 - value = "A"
// Yazma 2: 10:00:01 - value = "B"
// Sonuç: "B" kazanır (A kaybolur)

B. Vector Clocks
Çakışma tespiti yapar; çakışma varsa uygulama çözer.

csharp

// Vector Clock örneği
Node A: [A:1, B:0]
Node B: [A:0, B:1]
// Karşılaştırma: Eşzamanlı → ÇAKIŞMA VAR

C. CRDT (Conflict-Free Replicated Data Types)
Matematiksel olarak çakışmasız birleştirilebilen veri yapıları.

CRDT Türü Örnek
G-Counter (Grow-only) Sadece artan sayaç
PN-Counter Artan/azalan sayaç
OR-Set Ekleme/silme kümesi
LWW-Register Son yazan kazanır kayıt

csharp

// G-Counter (sadece artan) - çakışma imkansız
var counter = new GCounter();
counter.Increment("node-a", 5);
counter.Increment("node-b", 3);
var total = counter.Value; // 8 (her zaman doğru)

D. Uygulama Seviyesi Çözüm
Çakışma uygulamaya bırakılır (ör. sepet birleştirme).


7. .NET'te Eventual Consistency Uygulaması

A. Cosmos DB ile Session Consistency

csharp

// Cosmos DB - Session Consistency (Read-Your-Writes)
var client = new CosmosClient(connectionString, new CosmosClientOptions
{
    ConsistencyLevel = ConsistencyLevel.Session
});

// Kullanıcı kendi yazdığını hemen okur; ancak diğer kullanıcılar gecikmeli görebilir

Cosmos DB Tutarlılık Seviyeleri:

Seviye Tutarlılık Gecikme Kullanım
Strong En yüksek En yüksek Finansal işlemler
Bounded Staleness Sınırlı gecikme Yüksek Çok oyunculu oyunlar
Session Kullanıcı bazlı Orta E-ticaret sepeti
Consistent Prefix Sıralı ama gecikmeli Düşük Sosyal medya
Eventual En düşük En düşük Analytics, log

B. MassTransit ile Eventual Consistency

csharp

// Servis A: Sipariş oluştur ve event yayınla
public async Task CreateOrderAsync(CreateOrderCommand command)
{
    using var transaction = await _context.Database.BeginTransactionAsync();
    
    var order = new Order { Id = command.OrderId, Status = "Pending" };
    _context.Orders.Add(order);
    
    // Outbox'a event ekle (aynı transaction)
    _context.OutboxMessages.Add(new OutboxMessage
    {
        Id = Guid.NewGuid(),
        Type = "OrderCreated",
        Content = JsonSerializer.Serialize(new OrderCreatedEvent(order.Id)),
        OccurredOnUtc = DateTime.UtcNow
    });
    
    await _context.SaveChangesAsync();
    await transaction.CommitAsync();
}

// Servis B: Event'i dinle ve kendi verisini güncelle
public class OrderCreatedConsumer : IConsumer<OrderCreatedEvent>
{
    public async Task Consume(ConsumeContext<OrderCreatedEvent> context)
    {
        // Idempotency kontrolü
        if (await _processedMessages.ExistsAsync(context.MessageId.ToString()))
            return;

        // Kendi verisini güncelle
        await _inventoryService.ReserveStockAsync(context.Message.OrderId);

        await _processedMessages.MarkAsProcessedAsync(context.MessageId.ToString());
    }
}

C. Retry ve Idempotency

Eventual Consistency'de geçici tutarsızlıklar normaldir. Retry ve idempotency ile yönetilir.

csharp

var retryPolicy = Policy
    .Handle<InvalidOperationException>()  // Veri henüz hazır değil
    .WaitAndRetryAsync(5, retryAttempt => 
        TimeSpan.FromMilliseconds(Math.Pow(2, retryAttempt) * 100));

await retryPolicy.ExecuteAsync(async () =>
{
    var order = await _orderService.GetAsync(orderId);
    // Order henüz replike edilmemişse hata fırlatır, retry ile tekrar denenir
});

8. Gerçek Dünya Senaryosu: E-Ticaret Siparişi

Senaryo: Bir e-ticaret uygulamasında, sipariş oluşturma 3 servisi kapsıyor: Order, Payment, Inventory.

CAP Seçimi: Bu senaryoda CP (tutarlılık) kritiktir; çünkü stok aşımı (oversell) kabul edilemez.

Ancak: Tüm servisleri CP yapmak performansı düşürür. Hibrit yaklaşım:

İşlem Tutarlılık Modeli Gerekçe
Stok rezervasyonu Strong (CP) Oversell kabul edilemez
Sipariş oluşturma Session (Read-Your-Writes) Kullanıcı kendi siparişini hemen görmeli
Sipariş geçmişi Eventual (AP) Geçmiş veriler, gecikme kabul edilebilir
Ürün kataloğu Eventual (AP) Fiyat güncellemeleri dakikalar içinde yayılabilir
Analytics Eventual (AP) Gerçek zamanlı olmasına gerek yok

Akış:

text

1. Sipariş oluştur (CP - Order Service)
2. Ödeme al (CP - Payment Service)
3. Stok rezerve et (CP - Inventory Service)
   → Başarısız olursa telafi (Saga Pattern)
4. Kullanıcıya sipariş onayı gönder (Eventual - Notification Service)
5. Analytics'e event gönder (Eventual - Analytics Service)

9. CAP ve Eventual Consistency için En İyi Pratikler

Pratik Açıklama
CAP'i Bağlama Göre Seçin Her işlem için tutarlılık ihtiyacını değerlendirin.
Hibrit Yaklaşım Kullanın Kritik veriler CP, kritik olmayanlar AP.
Eventual Consistency'yi Dokümante Edin Hangi verinin ne kadar süre tutarsız olabileceğini belgeleyin.
Idempotency Sağlayın Retry ve tekrarlanan event'ler için.
Retry ve Timeout Kullanın Geçici tutarsızlıkları yönetmek için.
Çakışma Çözümü Belirleyin LWW, Vector Clock veya CRDT.
Monitoring Kurun Replikasyon gecikmesini (replication lag) izleyin.
Kullanıcı Deneyimi Tasarımı Tutarsızlık durumunda kullanıcıya anlamlı mesaj gösterin.
Test Edin Ağ bölünmesi senaryolarını test edin (Chaos Engineering).
PACELC'yi Unutmayın Bölünme olmadığında da gecikme-tutarlılık dengesi var.

10. CAP vs. Eventual Consistency: Özet

Kriter CP Sistemi AP Sistemi
Tutarlılık Güçlü (strong) Nihai (eventual)
Erişilebilirlik Bölünmede düşebilir Her zaman yüksek
Gecikme Yüksek (konsensüs gerekir) Düşük
Örnek ZooKeeper, Spanner Cassandra, DynamoDB
Kullanım Finans, envanter Sosyal medya, IoT
Veri Kaybı Yok Mümkün (LWW ile)

Sonuç

CAP Teoremi, dağıtık sistemlerde tutarlılık ve erişilebilirlik arasındaki kaçınılmaz dengeyi açıklar. Bölünme toleransı zorunlu olduğu için, gerçek seçim CP veya AP arasındadır. Eventual Consistency, AP sistemlerinin temel modelidir; yüksek erişilebilirlik ve düşük gecikme sağlar, ancak geçici tutarsızlıkları kabul eder. PACELC, bölünme olmadığında da gecikme-tutarlılık dengesi olduğunu hatırlatır. ACID vs BASE, iki farklı felsefeyi temsil eder. .NET ekosisteminde Cosmos DB, MassTransit ve Polly ile eventual consistency'yi güvenli bir şekilde uygulayabilirsiniz. Unutmayın: Her veri aynı tutarlılık seviyesini gerektirmez. Doğru mimari, iş ihtiyaçlarına göre her işlem için doğru dengeyi kuran mimaridir.

Tüm yazılar Soru ya da yorumun mu var? Yaz