Dağıtık sistemler dünyasında, güçlü tutarlılık ile sonlu tutarlılık arasındaki seçim genellikle uygulamanızın mimarisini belirler. Geleneksel ilişkisel veritabanları uzun süredir ACID uyumluluğunu önceliklendirirken, bulut-native dağıtık SQL veritabanlarının yükselişi mühendisleri veri bütünlüğü modellerini yeniden düşünmeye zorladı. Bu yazı, sonlu tutarlılık desenlerinin uygulanmasındaki incelikleri inceleyerek ölçeklenebilirliği veri güvenilirliği ile dengelemenize yardımcı olur.
Takasları Anlamak: CAP ve PACELC
Uygulamaya dalmadan önce, sonlu tutarlılığın neden var olduğunu anlamak kritik önem taşır. CAP teoremine göre, dağıtık bir sistem yalnızca üç özelliğin ikisini garanti edebilir: Tutarlılık, Erişilebilirlik ve Bölünme Toleransı. Modern coğrafi olarak dağıtık ortamlarda Bölünme Toleransı vazgeçilmezdir. Bu durum, güçlü tutarlılık ile erişilebilirlik arasında seçim yapmamıza neden olur.
CockroachDB, Google Spanner ve TiDB gibi dağıtık SQL veritabanları genellikle ayarlanabilir tutarlılık seviyeleri sunar. Geliştiricilerin gecikmeyi azaltmak ve işlem hacmini artırmak için oturum veya işlem düzeyinde sonlu tutarlılık seçeneğini tercih etmelerine olanak tanır. Ancak bu, taze olmayan okumalar ve yazma çakışmaları zorluğunu beraberinde getirir.
Pratik Uygulama: Oturum Düzeyinde Tutarlılık
Sonlu tutarlılığı geliştirici deneyimini riske atmadan uygulamanın en etkili yollarından biri oturum düzeyinde yapılandırma aracılığıyla gerçekleşir. Çoğu modern dağıtık SQL motoru, tutarlılık modunu oturum başına ayarlamanıza olanak tanır. Bu, aynı oturum içindeki sonraki okumaların, o oturum tarafından gerçekleştirilen yazmaları görmesini sağlar (Doğrulanabilir veya Kendi Yazılarınızı Okuma tutarlılığı), ancak oturumlar arası okumaların sonlu tutarlı olmasına izin verir.
Kritik olmayan okuma işlemleri için daha zayıf tutarlılık garantilerini kullanmak üzere bir bağlantı havuzunu nasıl yapılandırabileceğinize dair bir örnek:
// Dağıtık SQL sürücüsü kullanan Python örneği
from distributed_sql_driver import Connection, ConsistencyLevel
def get_user_profile(user_id):
# Zayıf tutarlılıkla bağlantı kur
# Bu, anında tutarlılıktan ziyade erişilebilirliği ve düşük gecikmeyi önceliklendirir
with Connection(consistency_level=ConsistencyLevel.EVENTUAL) as conn:
cursor = conn.cursor()
# Sorgu, profilin biraz taze olmayan bir versiyonunu döndürebilir
cursor.execute("SELECT * FROM user_profiles WHERE id = %s", (user_id,))
return cursor.fetchone()
Açıkça EVENTUAL (Sonlu) seçtiğimize dikkat edin. Yüksek trafikli senaryolarda bu, bölgeler arasındaki konsensüs algoritması (Raft veya Paxos gibi) üzerindeki yükü azaltarak okuma gecikmesini önemli ölçüde iyileştirir. Ancak, döndürülen verilerin başka bir düğümdeki en son yazmayı yansıtmayabileceği olasılığını ele almak için uygulama mantığınızı tasarlamalısınız.
Çakışmaları ve Birleştirme Stratejilerini Yönetme
Sonlu tutarlılık okumalar için güvenlidir, ancak yazmalar karmaşıklık getirir. İki kullanıcı farklı bölgelerde aynı kaydı aynı anda düzenlediğinde çakışmayı nasıl çözersiniz? Dağıtık SQL veritabanları genellikle iki strateji kullanır: son yazan kazanır (LWW) veya uygulama düzeyinde çözümleme ile çoklu sürüm eşzamanlılık denetimi (MVCC).
Çoğu uygulama için basit bir zaman damgası tabanlı çözümleme yeterlidir. Ancak finansal veya envanter sistemleri için daha sofistike bir birleştirmeye ihtiyacınız olabilir. Yaygın bir desen, verilerinizin yanına bir "sürüm" veya "vektör saati" depolamaktır. Bir güncelleme uygulandığında sistem sürümü kontrol eder. Bir çakışma tespit edilirse, uygulama mantığı alanları birleştirmek, yazmayı reddetmek veya sorunu yetkili bir birime iletmek gibi kararlar alabilir.
-- Çakışma çözümü için sürümleme destekleyen örnek şema
CREATE TABLE products (
product_id UUID PRIMARY KEY,
name STRING,
price DECIMAL,
version INT,
updated_at TIMESTAMP
);
-- Optimistik kilitleme kontrolü için sahte kod
BEGIN TRANSACTION;
SELECT version, price FROM products WHERE product_id = 'abc-123' INTO @current_version, @current_price;
-- Uygulama mantığı, @current_version'ın istemci tarafından gönderilen sürümle eşleşip eşleşmediğini kontrol eder
IF @current_version != @client_version THEN
RAISE CONFLICT_ERROR;
END IF;
UPDATE products
SET price = 100.00, version = version + 1, updated_at = NOW()
WHERE product_id = 'abc-123' AND version = @client_version;
COMMIT;
Sonuç: Doğru Tutarlılık Modelini Seçmek
Dağıtık SQL veritabanlarında sonlu tutarlılık uygulamak, veri bütünlüğünden vazgeçmekle ilgili değildir; bu, en önemli olduğu yerde uygulamakla ilgilidir. Oturum düzeyinde tutarlılık kontrollerini ve sağlam çakışma çözümleme stratejilerini kullanarak hem yüksek erişilebilirliğe hem de yüksek performanslı sistemler inşa edebilirsiniz.
Mühendis olarak göreviniz, iş gereksinimlerinizi uygun tutarlılık düzeyine eşlemektir. Sosyal medya akışları ve analiz panoları sonlu tutarlılıkta gelişir. Buna karşılık, banka defterleri ve envanter rezervasyonları güçlü tutarlılık gerektirir. Dağıtık SQL'in mekaniklerini anlamak, bu kararları güvenle almanızı ve mimarinizin verilerinize olan güveni bozmadan ölçeklenmesini sağlar.