GH GambleHub

Dağıtılmış kilitler

1) Neden (ve ne zaman) dağıtılmış kilitler gereklidir

Dağıtılmış engelleme, birkaç küme düğümü arasındaki kritik bir bölüm için karşılıklı dışlamayı garanti eden bir mekanizmadır. Tipik görevler:
  • Arka plan görevi/gölgelendiricisi için lider seçimi.
  • Paylaşılan bir kaynak üzerinde tek bir oyuncunun kısıtlanması (dosya hareketi, şema geçişleri, özel ödeme adımı).
  • Toplamın sıralı olarak işlenmesi (cüzdan/sipariş), aksi takdirde idempotency/sipariş elde etmek mümkün değilse.
Kilidi kullanmamak daha iyi olduğunda:
  • Eğer bir idempotent upsert, CAS (karşılaştır ve ayarla) veya anahtar başına sipariş yapabilirsiniz.
  • Kaynak değişmeli işlemlere izin veriyorsa (CRDT, sayaçlar).
  • Sorun bir mağazadaki bir işlemle çözülürse.

2) Tehdit modeli ve özellikleri

Başarısızlıklar ve komplikasyonlar:
  • Ağ: gecikmeler, bölme, paket kaybı.
  • İşlemler: GC duraklatma, stop-the-world, kilit yakalama sonrası çökme.
  • Zaman: Saat kayması ve yer değiştirme molası TTL yaklaşımları.
  • Repossession: Ağdan sonraki "zombi" süreci hala kalenin sahibi olduğunu düşünebilir.
İstenen özellikler:
  • Güvenlik: Birden fazla geçerli mal sahibi (güvenlik).
  • Beka: Sahibi başarısız olduğunda kilit serbest bırakılır (canlılık).
  • Adalet: Oruç yoktur.
  • Saat bağımsızlığı: Doğruluk duvar saatine bağlı değildir (veya eskrim belirteçleri ile telafi edilir).

3) Ana modeller

3. 1 Kiralama (kiralık kilit)

Kilit TTL ile verilir. Sahibi son kullanma tarihinden önce yenilemek zorundadır (kalp atışı/keepalive).

Artılar: Kendini emmeyi çökertir.
Riskler: Mal sahibi "sıkışmışsa've çalışmaya devam ederse, ancak uzantıyı kaybettiyse, çift mülkiyet ortaya çıkabilir.

3. 2 Eskrim belirteci

Her başarılı yakalamada, monoton olarak artan bir sayı verilir. Kaynak tüketicileri (veritabanı, kuyruk, dosya depolama) belirteci kontrol eder ve eski numarayla işlemleri reddeder.
Bu, TTL/kiralama ve ağ bölümleri için son derece önemlidir -'eski "sahibine karşı korur.

3. 3 Çekirdek kilitleri (CP sistemleri)

Dağıtılmış konsensüs kullanılır (Raft/Paxos; Etcd/ZooKeeper/Consul), kayıt bir konsensüs günlüğü ile ilişkilidir - çoğu düğüm ile bölünmüş bir beyin yoktur.

Artı: güçlü güvenlik garantileri.
Eksi: çoğunluğa duyarlılık (kaybolduğunda, hayatta kalabilirlik topaldır).

3. 4 AP kilidi (bellek içi/önbellek + çoğaltma)

Örneğin, bir Redis kümesi. Yüksek kullanılabilirlik ve hız, ancak ağ bölümleri için güçlü güvenlik garantileri olmadan. Çürüğün yan tarafında çit gerektirir.

4) Platformlar ve desenler

4. 1 etcd/ZooKeeper/Consul (güçlü kilitler için önerilir)

Geçici düğümler (ZK) veya oturumlar/kiralamalar (etcd): oturum canlı iken anahtar var.
Oturum keepalive; Çekirdek kaybı - oturum sona erer - kilit serbest bırakılır.
Bekleme kuyruğu için dizi düğümleri (ZK 'EPHEMERAL _ SEQUENTIAL') - adil.

Etcd'de taslak (Git):
go cli, _:= clientv3. New(...)
lease, _:= cli. Grant(ctx, 10)            // 10s lease sess, _:= concurrency. NewSession(cli, concurrency. WithLease(lease. ID))
m:= concurrency. NewMutex(sess, "/locks/orders/42")
if err:= m. Lock(ctx); err!= nil { / handle / }
defer m. Unlock(ctx)

4. 2 Redis (düzgün)

Klasik - 'SET anahtar değeri NX PX tl'.

Sorunlar:
  • Replication/feilover eşzamanlı sahiplere izin verebilir.
  • Birden fazla örnekten gelen redlock, riski azaltır, ancak ortadan kaldırmaz; Güvenilir olmayan bir ağa sahip ortamlarda tartışmalıdır.

Redis'i hızlı bir koordinasyon katmanı olarak kullanmak daha güvenlidir, ancak her zaman hedef kaynaktaki eskrim belirtecini tamamlar.

Örnek (Lua-unlock):
lua
-- release only if value matches if redis. call("GET", KEYS[1]) == ARGV[1] then return redis. call("DEL", KEYS[1])
else return 0 end

4. 3 DB kilidi

PostgreSQL danışma kilitleri: Postgres kümesi içinde kilit (işlem/oturum).
Tüm kritik bölümler zaten aynı veritabanında olduğunda iyidir.

SQL:
sql
SELECT pg_try_advisory_lock(42); -- take
SELECT pg_advisory_unlock(42); -- let go

4. 4 Dosya/bulut kilitleri

S3/GCS + object metadata lock with 'If-Match' (ETag) conditions - özünde CAS.
Yedeklemeler/geçişler için uygundur.

5) Güvenlik kilidi tasarımı

5. 1 Sahip kimliği

'owner _ id' (# process # pid # start _ time node) + doğrulama kilidini açmak için rasgele belirteç saklayın.
Tekrarlanan kilit açma, başkasının kilidini kaldırmamalıdır.

5. 2 TTL ve uzantısı

TTL <T_fail_detect (arıza tespit süresi) ve p99 ≥ kritik kesit çalışması × yedek.
Yenileme - periyodik olarak (örneğin, her 'TTL/3'), son tarih ile.

5. 3 Bir çürük üzerinde eskrim belirteci

Dış kaynağı değiştiren bölüm 'fencing _ token'ı geçmelidir.

Lavabo (DB/cache/storage) 'last _ token' depolar ve daha küçük olanları reddeder:
sql
UPDATE wallet
SET balance = balance +:delta, last_token =:token
WHERE id =:id AND:token > last_token;

5. 4 Bekleme Kuyruğu ve Adalet

ZK'da - 'EPHEMERAL _ SEQUENTIAL've gözlemciler: istemci en yakın selefin serbest bırakılmasını bekliyor.
Etcd'de - revizyon/sürümleme ile tuşlar; 'mod _ revision'ile sipariş verin.

5. 5 Bölünmüş beyin davranışı

CP yaklaşımı: Yeterli çoğunluk olmadan, kilit alamazsınız - ayakta durmak güvenliği kırmaktan daha iyidir.
AP yaklaşımı: bölünmüş adalarda ilerlemeye izin verilir - eskrim gereklidir.

6) Lider seçimi

Etcd/ZK'da "lider" özel bir epemerik anahtardır; Geri kalanlar değişiklikler için kaydolur.
Lider kalp atışları yazar; kayıp - yeniden seçim.
Tüm lider operasyonlarına bir eskrim belirteci (çağ/revizyon numarası) ile eşlik edin.

7) Hatalar ve bunların işlenmesi

Müşteri kilidi aldı, ancak çalışmak için çöktü - norm, kimse acı çekmeyecek; TTL/seans serbest bırakılacaktır.

Kilit, işin ortasında sona erdi:
  • Zorunlu bekçi: uzatma başarısız olursa, kritik bölümü durdurun ve geri dönün/telafi edin.
  • "Daha sonra bitir" yok: kilit olmadan kritik bölüme devam edilemez.

Uzun bir duraklama (GC/stop-the-world) - uzatma gerçekleşmedi, diğeri kilidi aldı. İş akışı, sahiplik kaybını (keepalive channel) tespit etmeli ve iptal etmelidir.

8) Dedloki, öncelikler ve inversiyon

Dağıtılmış bir dünyada Dedloki nadirdir (genellikle bir kale vardır), ancak birkaç kale varsa, tek bir sipariş alma (kilit siparişi).
Öncelikli ters çevirme: Düşük öncelikli bir sahip, yüksek öncelikli olanlar beklerken bir kaynağı tutar. Çözümler: TTL limitleri, ön alım (iş izin veriyorsa), kaynağın kesilmesi.
Oruç: Adalet için bekleme kuyrukları (ZK alt sıra düğümleri) kullanın.

9) Gözlemlenebilirlik

Metrikler:
  • 'lock _ acquire _ total {status = ok' timeout 'error}'
  • 'lock _ hold _ seconds {p50, p95, p99}'
  • 'eskrim _ belirteç _ değeri' (monotonluk)
  • 'lease _ renew _ fail _ total'
  • 'split _ brain _ prevented _ total' (yeterli çoğunluk olmadığı için reddedilen girişim sayısı)
  • 'preemptions _ total', 'wait _ queue _ len'
Günlükler/izleme:
  • 'lock _ name', 'owner _ id', 'token','tl ',' entry ',' wait _ time _ ms ',' path '(для ZK),' mod _ revision '(etcd).
  • "acquire" critical section "release sonucuyla birlikte yayılır.
Uyarılar:
  • Büyüme 'lease _ renew _ fail _ total'.
  • 'lock _ hold _ seconds {p99}'> SLO.
  • "Yetim" kilitler (kalp atışı olmadan).
  • Şişirilmiş bekleme listeleri.

10) Vaka çalışmaları

10. 1 Güvenli Redis çit ile kilitleyin (pseudo)

1. Token sayacını güvenilir bir mağazada saklıyoruz (örneğin, Postgres/etcd).
2. 'SET NX PX' başarılı olursa, belirteci okur/artırır ve kaynaktaki tüm değişiklikleri veritabanı/hizmette işaretlenmiş belirteçle yaparız.

python acquire token = db. next_token ("locks/orders/42") # monotone ok = redis. set("locks:orders:42", owner, nx=True, px=ttl_ms)
if not ok:
raise Busy()

critical op guarded by token db. exec("UPDATE orders SET... WHERE id=:id AND:token > last_token",...)
release (compare owner)

10. 2 etcd Mutex + watchdog (Git)

go ctx, cancel:= context. WithCancel(context. Background())
sess, _:= concurrency. NewSession(cli, concurrency. WithTTL(10))
m:= concurrency. NewMutex(sess, "/locks/job/cleanup")
if err:= m. Lock(ctx); err!= nil { /... / }

// Watchdog go func() {
<-sess. Done ()//loss of session/quorum cancel ()//stop working
}()

doCritical (ctx )//must respond to ctx. Done()
_ = m. Unlock(context. Background())
_ = sess. Close()

10. 3 ZK'da Liderlik (Java, Küratör)

java
LeaderSelector selector = new LeaderSelector(client, "/leaders/cron", listener);
selector. autoRequeue();
selector. start(); // listener. enterLeadership() с try-finally и heartbeat

10. Son teslim tarihi olan 4 Postgres danışma kilidi (SQL + uygulaması)

sql
SELECT pg_try_advisory_lock(128765); -- attempt without blocking
-- if false --> return via backoff + jitter

11) Test oyun kitapları (Oyun Günleri)

Çekirdek kaybı: 1-2 etcd düğümünü devre dışı bırakın - kilidi alma girişimi geçmemelidir.
GC-pause/stop-the-world: yapay olarak sahibinin akışını geciktirir - bekçi köpeğinin çalışmayı kesintiye uğrattığını kontrol edin.
Bölünmüş beyin: sahibi ile kalenin tarafı arasındaki ağ ayrımının emülasyonu - yeni sahibi daha yüksek bir eskrim belirteci alır, eski olanı mavi tarafından reddedilir.
Saat eğriltme/sürüklenme: saati sahibinden uzaklaştırın (Redis/kiralama için) - doğruluğun belirteçler/çekler tarafından sağlandığından emin olun.
Yayınlanmadan önce kilitlenme: process crash - lock TTL/session ile serbest bırakılır.

12) Anti-desenler

Harici bir kaynağa erişirken çitsiz TTL kilidini temizleyin.
Doğruluk için yerel zamana güvenin (HLC/eskrim yok).
Kilitlerin bir Redis master aracılığıyla, feilover'lı ve kopyaların onaylanmadığı bir ortamda dağıtılması.
Sonsuz kritik bölüm (TTL "çağlar için").
'Owner _ id'/belirteci işaretlemeden başka birinin kilidini kaldırma.
Backoff + jitter eksikliği - girişimlerin fırtınası.
'her şey için'tek bir küresel kilit - bir çatışma çantası; Anahtar sharding daha iyidir.

13) Uygulama kontrol listesi

  • Tanımlanan kaynak tipi ve CAS/kuyruk/idempotency ile vazgeçilebilir.
  • Mekanizma seçildi: CP için etcd/ZK/Konsül; Redis/cache - sadece eskrim ile.
  • Uygulanan: 'owner _ id', TTL + uzantısı, bekçi, doğru kilit açma.
  • Dış kaynak eskrim belirtecini kontrol eder (monotonluk).
  • Bir liderlik stratejisi ve yük devretme var.
  • Yapılandırılmış metrikler, uyarılar, günlük belirteçleri ve revizyonlar.
  • Backoff + jitter ve edinme zaman aşımları sağlanır.
  • Düzenlenen oyun günleri: Yeterli çoğunluk, bölünmüş beyin, GC duraklar, saat eğrilmesi.
  • Birkaç kilit alma prosedürünün belgelenmesi (gerekirse).
  • brownout planı - kilit mevcut olmadığında ne yapmalı.

14) SSS

S: 'SET NX PX' Redis kilidi yeterli mi?
C: Yalnızca kaynak eskrim belirtecini kontrol ederse. Aksi takdirde, ağ bölümleme ile iki sahip mümkündür.

S: "Varsayılan olarak'ne seçilir?
C: Kesin garantiler için - etcd/ZooKeeper/Consul (CP). Bir veritabanı içinde kolay görevler için - danışma kilitleri Postgres. Redis - sadece eskrim ile.

S: Hangi TTL koymak için?
C: 'TTL ≥ p99 kritik bölüm süresi × 2've zombileri hızlı bir şekilde temizlemek için yeterince kısa. "Yenileme - her 'TTL/3'.

S: Oruç tutmaktan nasıl kaçınılır?
A: Sıralı bekleme kuyruğu (ZK sıralı) veya adalet algoritması; Girişimlerin sınırı ve adil planlama.

S: Zaman senkronizasyonuna ihtiyacım var mı?
C: Doğruluk için - hayır (eskrim kullanın). Operasyonel öngörülebilirlik için, evet (NTP/PTP), ancak kilit mantığı için duvar saatine güvenmeyin.

15) Toplam

Güvenilir dağıtılmış kilitler, kiralama + keepalive ile yeterli çoğunluk seviyelerine (etcd/ZK/Consul) inşa edilir ve mutlaka değiştirilmekte olan kaynağın seviyesinde eskrim belirteci ile desteklenir. Eskrim olmadan herhangi bir TTL/Redis yaklaşımı bölünmüş beyin riskidir. İlk önce nedensellik ve idempotans hakkında düşünün, onlarsız imkansız olduğu yerlerde kilitler kullanın, hata modlarını ölçün, test edin - ve "kritik bölümleriniz", olayların sayısında değil, yalnızca anlam açısından kritik kalacaktır.

Contact

Bizimle iletişime geçin

Her türlü soru veya destek için bize ulaşın.Size yardımcı olmaya her zaman hazırız!

Entegrasyona başla

Email — zorunlu. Telegram veya WhatsApp — isteğe bağlı.

Adınız zorunlu değil
Email zorunlu değil
Konu zorunlu değil
Mesaj zorunlu değil
Telegram zorunlu değil
@
Telegram belirtirseniz, Email’e ek olarak oradan da yanıt veririz.
WhatsApp zorunlu değil
Format: +ülke kodu ve numara (örneğin, +90XXXXXXXXX).

Butona tıklayarak veri işlemenize onay vermiş olursunuz.