CAP Teoremi Detaylı Anlatım
CAP teoremi (Brewer teoremi olarak da bilinir), dağıtık sistemlerde aşağıdaki üç özellikten sadece ikisinin aynı anda sağlanabileceğini belirtir:
1. C - Consistency (Tutarlılık)
- Tüm düğümler aynı anda aynı veriyi görür
- Bir yazma işleminden sonra, tüm okuma işlemleri en güncel veriyi döndürür
- Strong consistency olarak da bilinir
2. A - Availability (Erişilebilirlik)
- Her istek başarılı bir yanıt alır (hata durumunda bile)
- Sistem her zaman çalışır durumdadır
- Her düğüm her zaman istekleri işleyebilir
3. P - Partition Tolerance (Bölüm Toleransı)
- Ağ bölünmeleri (partition) durumunda sistem çalışmaya devam eder
- Düğümler arası iletişim kopsa bile sistem cevap verebilir
- Dağıtık sistemlerde bu genellikle zorunludur
CAP Teoremi Kombinasyonları
CP Sistemler (Consistency + Partition Tolerance)
// CP Sistem Örneği - Senkron Replikasyon
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
class CPSystem {
private ConcurrentHashMap<String, String> data = new ConcurrentHashMap<>();
private ReentrantLock lock = new ReentrantLock();
private boolean partitionDetected = false;
// Yazma işlemi - tüm düğümlere yazılmalı
public boolean write(String key, String value) {
lock.lock();
try {
if (partitionDetected) {
// Partition varsa yazma işlemini reddet (Consistency korunur)
System.out.println("Network partition detected - Write rejected");
return false;
}
// Tüm replikalara yaz (senkron)
boolean allReplicasUpdated = writeToAllReplicas(key, value);
if (allReplicasUpdated) {
data.put(key, value);
return true;
}
return false;
} finally {
lock.unlock();
}
}
// Okuma işlemi - en güncel veri döndürülmeli
public String read(String key) {
lock.lock();
try {
if (partitionDetected) {
// Partition varsa sadece tutarlı veriyi döndür
return getConsistentData(key);
}
return data.get(key);
} finally {
lock.unlock();
}
}
private boolean writeToAllReplicas(String key, String value) {
// Tüm düğümlere yazma mantığı
return true; // Basitleştirilmiş
}
private String getConsistentData(String key) {
// Tutarlı veri getirme mantığı
return data.get(key);
}
public void setPartitionDetected(boolean detected) {
this.partitionDetected = detected;
}
}
AP Sistemler (Availability + Partition Tolerance)
// AP Sistem Örneği - Eventual Consistency
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class APSystem {
private ConcurrentHashMap<String, String> data = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Long> versionVector = new ConcurrentHashMap<>();
private ExecutorService replicationExecutor = Executors.newFixedThreadPool(5);
// Yazma işlemi - her zaman kabul edilir
public boolean write(String key, String value) {
// Yerel düğüme yaz
long timestamp = System.currentTimeMillis();
data.put(key, value);
versionVector.put(key, timestamp);
// Asenkron olarak diğer düğümlere replike et
replicationExecutor.submit(() -> {
try {
replicateToOtherNodes(key, value, timestamp);
} catch (Exception e) {
System.err.println("Replication failed: " + e.getMessage());
// Replikasyon hatası olsa bile yazma başarılı sayılır
}
});
return true; // Her zaman başarılı
}
// Okuma işlemi - her zaman yanıt döndürülür
public String read(String key) {
String value = data.get(key);
if (value == null) {
return "DEFAULT_VALUE"; // Her zaman bir değer döndür
}
return value;
}
private void replicateToOtherNodes(String key, String value, long timestamp) {
// Diğer düğümlere asenkron replikasyon
System.out.println("Replicating " + key + " to other nodes");
// Çakışma çözümü - son yazılan kazanır
Long existingTimestamp = versionVector.get(key);
if (existingTimestamp == null || timestamp > existingTimestamp) {
// Diğer düğümleri güncelle
updateOtherNodes(key, value);
}
}
private void updateOtherNodes(String key, String value) {
// Diğer düğümleri güncelleme mantığı
}
public void shutdown() {
replicationExecutor.shutdown();
try {
replicationExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
CA Sistemler (Consistency + Availability)
// CA Sistem Örneği - Partition toleransı yok
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class CASystem {
private ConcurrentHashMap<String, String> data = new ConcurrentHashMap<>();
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private boolean networkHealthy = true;
// Yazma işlemi
public boolean write(String key, String value) {
if (!networkHealthy) {
throw new RuntimeException("Network partition - System unavailable");
}
lock.writeLock().lock();
try {
// Tek bir kopyaya yaz, ama tutarlı ol
data.put(key, value);
return true;
} finally {
lock.writeLock().unlock();
}
}
// Okuma işlemi
public String read(String key) {
if (!networkHealthy) {
throw new RuntimeException("Network partition - System unavailable");
}
lock.readLock().lock();
try {
return data.getOrDefault(key, "NOT_FOUND");
} finally {
lock.readLock().unlock();
}
}
public void setNetworkHealthy(boolean healthy) {
this.networkHealthy = healthy;
}
}
Gerçek Dünya Örnekleri
1. MongoDB (CP varsayılan)
// MongoDB CP yaklaşımı örneği
import com.mongodb.*;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
class MongoDBExample {
private MongoClient mongoClient;
private MongoCollection<Document> collection;
public MongoDBExample() {
// Write concern: MAJORITY -> CP yaklaşımı
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString("mongodb://localhost:27017"))
.writeConcern(WriteConcern.MAJORITY)
.readPreference(ReadPreference.primary())
.build();
mongoClient = MongoClients.create(settings);
collection = mongoClient.getDatabase("testdb")
.getCollection("testcollection");
}
public void writeWithConsistency(String key, String value) {
Document doc = new Document("key", key)
.append("value", value)
.append("timestamp", System.currentTimeMillis());
try {
// Majority write concern - çoğunluk onaylayana kadar bekle
collection.withWriteConcern(WriteConcern.MAJORITY)
.insertOne(doc);
System.out.println("Write successful with majority acknowledgment");
} catch (MongoException e) {
System.err.println("Write failed - Consistency ensured: " + e.getMessage());
}
}
}
2. Cassandra (AP)
// Cassandra AP yaklaşımı örneği
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.*;
class CassandraExample {
private CqlSession session;
public CassandraExample() {
session = CqlSession.builder()
.withLocalDatacenter("datacenter1")
.build();
}
public void writeWithAvailability(String key, String value) {
// Consistency level: ONE -> AP yaklaşımı
PreparedStatement prepared = session.prepare(
"INSERT INTO test.keyspace (key, value) VALUES (?, ?) USING TIMESTAMP ?"
);
BoundStatement bound = prepared.bind()
.setString(0, key)
.setString(1, value)
.setLong(2, System.currentTimeMillis());
// Sadece bir düğümün onayı yeterli
Statement statement = bound.setConsistencyLevel(DefaultConsistencyLevel.ONE);
try {
session.execute(statement);
System.out.println("Write accepted (eventual consistency)");
} catch (Exception e) {
System.err.println("Write failed but system remains available: " + e.getMessage());
}
}
public String readWithAvailability(String key) {
// Consistency level: ONE -> AP yaklaşımı
SimpleStatement statement = SimpleStatement.builder(
"SELECT value FROM test.keyspace WHERE key = ?"
).addPositionalValue(key)
.setConsistencyLevel(DefaultConsistencyLevel.ONE)
.build();
try {
Row row = session.execute(statement).one();
return row != null ? row.getString("value") : null;
} catch (Exception e) {
System.err.println("Read failed but returning stale data: " + e.getMessage());
return getStaleData(key); // Eski veriyi döndür
}
}
private String getStaleData(String key) {
// Önbellekten veya yerel kopyadan eski veriyi döndür
return "CACHED_VALUE";
}
}
Önemli Noktalar
-
Ağ Bölünmesi (Partition) Kaçınılmazdır
- Dağıtık sistemlerde ağ sorunları her zaman olabilir
- Bu nedenle P (Partition Tolerance) genellikle zorunludur
-
Trade-off'lar
- CP: Tutarlılık için erişilebilirlikten ödün verilir
- AP: Erişilebilirlik için tutarlılıktan ödün verilir
- CA: Teorik olarak mümkün ama pratikte gerçekçi değil
-
Gerçek Uygulamalar
- Bankacılık sistemleri: CP tercih edilir
- Sosyal medya: AP tercih edilir
- E-ticaret: Ürün stoğu CP, ürün yorumları AP
-
Esneklik
- Birçok modern veritabanı yapılandırılabilir CAP özellikleri sunar
- İhtiyaca göre consistency level ayarlanabilir
CAP teoremi, dağıtık sistem tasarımında temel bir kılavuzdur ve sistem gereksinimlerine göre doğru dengeyi kurmak önemlidir.