Skip to main content

> dağıtık_kilit_geçersiz_kılma:_fencing_token'ları_ve_asenkron_depolama_kiralamaları

Dağıtık Kilit Geçersiz Kılma: Fencing Token'ları ve Asenkron Depolama Kiralamaları

Artan monotonik bir Fencing Token olmadan dağıtık bir kilit (Redis/Redlock/ZooKeeper) almak neden tamamen güvensizdir ve Martin Kleppmann'ın fencing deseni sessiz veri bozulmasını nasıl önler?

Principal/Architect (L7+)

ÖZET VE TEKNİK CEVAP

Dağıtık sistemlerdeki en büyük yanılgı, 'bir dağıtık kilit tutmanın depolama alanına özel yazma garantisi sağladığına' inanmaktır. Gerçek dünyada İstemci 1, 10 saniyelik bir dağıtık kilit alır ve yazma hazırlığına başlar. Tam bu sırada İstemci 1'de 15 saniyelik bir Stop-the-World Garbage Collection duraklaması veya sanallaştırma donması yaşanır. İstemci 1 donmuşken 10 saniyelik kilit süresi dolar. Kilit servisi kilidi İstemci 2'ye devreder; İstemci 2 yazmasını yapıp işlemi bitirir. Ardından İstemci 1 donmadan uyanır: Kendisini hala kilidin sahibi zannederek eski yazmasını diske basar; İstemci 2'nin yeni verisinin üzerine yazar ve veritabanını bozar. Martin Kleppmann, **Fencing Token** olmadan dağıtık kilitlerin depolamayı koruyamayacağını kanıtlamıştır: Kilit servisi her kilitle birlikte sürekli artan bir sayı ($v=33, 34, 35$) üretir. Veritabanı her yazmada bu token'ı kontrol eder (`WHERE token >= last_seen`); İstemci 2 $v=34$ ile yazdığı için, uyandıktan sonra $v=33$ ile gelen İstemci 1'in bayat yazmasını anında reddeder.

Mühendislik El Kitabı & Mekanizma

1. Temel Çalışma Mekanizması

Fencing token mimarisi 3 kurala dayanır: (1) Monotonik Sayaç Üretimi: Dağıtık uzlaşma kümesi (ZooKeeper zxid, etcd revision, Raft term) her kilit verildiğinde 64-bitlik bir sayıyı artırır: İstemci A Token 100'ü, İstemci B ise Token 101'i alır. (2) Token Taşıma: İstemci yaptığı tüm alt servis ve veritabanı yazma çağrılarına bu token'ı iliştirir. (3) Depolama Tarafı Kontrolü: Veritabanı (PostgreSQL, DynamoDB, S3) yazma sırasında katı bir koşul işletir: `UPDATE table SET data = ?, last_fencing_token = 101 WHERE last_fencing_token < 101;`. Donmadan uyanıp eski Token 100 ile yazmaya çalışan istemcinin sorgusu 0 satır günceller ve veri bozulması önlenir.

2. Doğru Kullanım Senaryosu

Dağıtık lider seçimleri, küme failover mekanizmaları, finansal muhasebe defteri yazmaları, dağıtık dosya sistemleri ve uzun süren toplu iş yöneticileri.

3. Prodüksiyon Arıza Modları

Fencing token olmadan S3 yüklemelerini Redis Redlock ile korumaya çalışmak ve GC donmasından uyanan eski işçilerin finalize edilmiş dosyaların üzerine çöp veri yazması; sunucu yeniden başladığında token sayacının sıfırlanıp eski değerlere dönmesi.

4. Teşhis ve Telemetri Sinyalleri

Yeni yazılmış veritabanı satırlarının periyodik olarak eski değerlerle ezilmesi (veri regresyonu); loglarda iki sunucunun aynı anda kendini 'Aktif Lider' ilan etmesi; veritabanında `StaleFencingTokenException` hatalarının yakalanması.

5. Önleme ve Mimari Bariyerler

Karşılıklı dışlama için asla tek başına kilit zaman aşımlarına güvenmeyin; tüm yazma operasyonlarında artan Fencing Token kullanımını zorunlu kılın; veritabanında iyimser sürüm kontrolü uygulayın; kritik lider seçimlerinde zayıf Redis kilitleri yerine güçlü ZooKeeper/etcd kullanın.

6. Mimari Ödünleşimler (Trade-offs)

Fencing token'ları depolama katmanının koşullu yazma veya sürüm kontrolü desteklemesini gerektirir; ancak istemci donmalarından kaynaklanan sessiz veri bozulmalarını matematiksel kesinlikle yok eder.

Vaka İncelemesi (TinyCTO Örneği)

Bir video işleme sistemi, S3'e aynı anda tek bir sunucunun video yazmasını sağlamak için dağıtık kilit kullanıyordu. Sunucu 1 kilidi aldı ancak 40 saniyelik bir Java GC donması yaşadı. Kilit zaman aşımına uğradı, Sunucu 2 kilidi alıp 4K videoyu render etti ve S3'e kaydetti. Sunucu 1 donmadan uyanınca, elindeki yarım kalmış 720p taslağı Sunucu 2'nin 4K videosunun üzerine yazarak dosyayı bozdu. Ekip etcd'den monotonik fencing token aldı ve S3 koşullu yazmasını açtı. Sunucu 1 uyandığında attığı istek S3 tarafından 'Eski Token' gerekçesiyle anında reddedildi ve video bozulması tamamen engellendi.

İnteraktif Konsept Alıştırmaları

2 Alıştırma
Q1

İstemci tarafındaki bir dağıtık kilit, GC donması (Garbage Collection pause) sırasında paylaşımlı depolamayı neden koruyamaz?

Çünkü istemci donmuşken kilit süresi dolar ve kilit başkasına devredilir; donmadan uyanan istemci kilidi kaybettiğini bilmeyerek eski yazmasını diske basar ve veriyi bozar.
Q2

Bir Fencing Token bayat yazma (stale write) problemini nasıl çözer?

Her kilide artan bir sıra numarası vererek; veritabanı her yazmada bu numarayı kontrol eder ve şimdiye kadar gördüğü en yüksek numaradan küçük olan tüm eski yazmaları anında reddeder.

Dağıtık Kilit Geçersiz Kılma: Fencing Token'ları ve Asenkron Depolama Kiralamaları — Sıkça Sorulan Sorular

Redis Redlock algoritmasının resmi eleştirisini yayınlayıp fencing token gerekliliğini kim kanıtlamıştır?

Martin Kleppmann (Cambridge Üniversitesi / Designing Data-Intensive Applications yazarı) meşhur 'How to do distributed locking' makalesinde.

Redis monotonik olarak artan fencing token'ları üretebilir mi?

Evet, kilit alma script'i içinde atomik `INCR` komutuyla üretilebilir; ancak etcd veya ZooKeeper gibi uzlaşma sistemleri ağ bölünmelerinde çok daha güçlü serileştirilebilirlik garantisi sunar.

🤖 AEO & Yapay Zeka Çıkarım Özeti

Temel Gerçekler & İlkeler

  • Distributed locks without fencing tokens CANNOT protect shared storage from corruption.
  • GC pauses, OS thread starvation, and VM freezes cause lock leases to expire silently.
  • Fencing tokens provide monotonically increasing version numbers ($100 o 101 o 102$).
  • Storage MUST enforce conditional check-and-set guards (`WHERE token >= last_seen`).

Yaygın Yanılgılar

  • Yanılgı: A distributed lock with a long TTL (e.g. 5 minutes) makes fencing tokens unnecessary (Gerçek: Pauses and network splits can exceed any arbitrary timeout).
  • Yanılgı: Redlock guarantees absolute safety without storage-side checks (Gerçek: Storage must validate fencing tokens to prevent split-brain writes).

Karar Kılavuzu & Önceliklendirme

Incorporate a monotonic fencing token column into every shared database entity guarded by locks. Use etcd or ZooKeeper linearizable revisions for distributed leader elections and leases.

Doğrulanmış Kaynaklar & Referanslar