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

  1. 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
  2. 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
  3. 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
  4. 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.