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.