Taqsimlangan qulflar
1) Nima uchun (va qachon) taqsimlangan blokirovkalar kerak
Taqsimlangan blokirovka - klastyerning bir necha uzellari orasidagi tanqidiy seksiya uchun o’zaro istisno qilinishini kafolatlovchi mexanizm. Namunaviy vazifalar:- Orqa fon vazifasi uchun yetakchilik (leader election).
- Yagona ijrochini umumiy resurs ustidan cheklash (fayllarni ko’chirish, sxema migratsiyasi, eksklyuziv to’lov qadami).
- Agregatni (wallet/order) ketma-ket qayta ishlash, agar boshqacha idempotentlikka/tartibga solishga erishib boʻlmasa.
- Agar idempotent upsert, CAS (compare-and-set) yoki kalit navbati (per-key ordering) qilish mumkin boʻlsa.
- Agar manba kommutativ operatsiyalarga ruxsat bersa (CRDT, hisoblagichlar).
- Agar muammo bitta ombordagi tranzaksiya orqali hal qilinsa.
2) Tahdidlar modeli va xossalari
Nosozliklar va murakkabliklar:- Tarmoq: kechikishlar, ajratish (partition), paketlarni yoʻqotish.
- Jarayonlar: GC pauza, stop-the-world, qulf olingandan so’ng.
- Vaqt: soat drifti va siljish TTL yondashuvlarini buzadi.
- Qayta egalik qilish: «zombi» protsessi tarmoqdan keyin qulfga ega deb o’ylashi mumkin.
- Xavfsizlik: bittadan ortiq haqiqiy egasi (safety).
- Omon qolish: qulf egasi ishlamay qolganda (liveness) bo’shatiladi.
- Adolat: ochlik yoʻq.
- Soatdan mustaqillik: toʻgʻrilik wall-clock ga bogʻliq emas (yoki fencing tokens bilan qoplanadi).
3) Asosiy modellar
3. 1 Lease (ijara qal’asi)
Qulf TTL bilan beriladi. Egasi uni muddati tugagunga qadar uzaytirishi shart (heartbeat/keepalive).
Afzalliklari: kreshda o’zini o’zi ta’minlash.
Xavf-xatarlar: agar egasi «osilib» qolsa va ishlashda davom etsa, lekin uzaytirishni yo’qotsa, ikki tomonlama egalik qilish paydo bo’lishi mumkin.
3. 2 Fencing token (to’siq tokeni)
Har bir muvaffaqiyatli qo’lga olishda monoton o’suvchi raqam beriladi. Resurs iste’molchilari (DB, navbat, fayl ombori) tokenni tekshiradilar va eski raqam bilan operatsiyalarni rad etadilar.
Bu TTL/lease va tarmoq bo’linmalarida juda muhimdir - «eski» egasidan himoya qiladi.
3. 3 Quorum-qulflar (CP-tizimlar)
Taqsimlangan konsensusdan foydalaning (Raft/Paxos; etcd/ZooKeeper/Consul), yozuv konsensus logi bilan bog’liq → ko’pgina tugunlarda split breyn yo’q.
Plyus: kuchli xavfsizlik kafolatlari.
Minus: kvorumga sezgirlik (uni yo’qotganda omon qolish).
3. 4 AP qulflar (in-memory/kesh + replikatsiya)
Masalan, Redis klasteri. Yuqori foydalanish imkoniyati va tezligi, lekin tarmoq bo’linishlarida xavfsizlikning qat’iy kafolatlarisiz. Ko’k tomonda fencing talab qilinadi.
4) Platformalar va patternlar
4. 1 etcd/ZooKeeper/Consul (strong locks uchun tavsiya etiladi)
Efemer tugunlari (ZK) yoki/leases (etcd): kalit hozircha mavjud.
Sessiya keepalive; kvorumni yo’qotish → sessiya tugaydi → qulf bo’shatiladi.
Navbat kutish uchun tartib uzellari (ZK’EPHEMERAL _ SEQUENTIAL’) → adolat.
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 (ehtiyotkorlik bilan)
Klassika -’SET key value NX PX ttl’.
Muammolar:- Replikatsiya/faylover bir vaqtning oʻzida egalariga ruxsat berishi mumkin.
- Bir nechta instansiyalardan Redlock xavfni kamaytiradi, lekin bartaraf etmaydi; ishonchsiz tarmoqli muhitlarda bahsli.
Redisni tezkor muvofiqlashtiruvchi qatlam sifatida ishlatish xavfsiz, ammo maqsadli manbada har doim fencing tokenini toʻldirish mumkin.
Misol (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-qulflar
PostgreSQL advisory locks: Postgres klasteridagi lok (jarayon/sessiya).
Barcha tanqidiy bo’limlar bitta DBda bo’lsa yaxshi bo’ladi.
sql
SELECT pg_try_advisory_lock(42); -- take
SELECT pg_advisory_unlock(42); -- let go
4. 4 Fayl/bulut qulflari
S3/GCS +’If-Match’(ETag) shartlari bo’lgan ob’ektli meta ma’lumotlar lok → mohiyatan CAS.
Bekap/migratsiya uchun mos keladi.
5) Xavfsiz qulf dizayni
5. 1 Egasining aynan
’owner _ id’ (tugun #процесс #pid #start_time) + tasodifiy tokenni unlockda solishtirish uchun saqlang.
Unlock boshqa birovning qulfini olib tashlamasligi kerak.
5. 2 TTL va uzaytirish
TTL <T_fail_detect (nosozlikni aniqlash vaqti) va kritik seksiya ishining ≥ p99 × zaxirasi.
Uzaytirish - davriy (masalan, har bir’TTL/3’), deadline bilan.
5. 3 Fencing token
Tashqi resursni oʻzgartiruvchi seksiya’fencing _ token’ni uzatishi kerak.
Sink’last _ token’ni saqlaydi va kichiklarini rad etadi:sql
UPDATE wallet
SET balance = balance +:delta, last_token =:token
WHERE id =:id AND:token > last_token;
5. 4 Kutish navbati va adolat
ZK -’EPHEMERAL _ SEQUENTIAL’va kuzatuvchilar: mijoz eng yaqin oʻtmishdoshini ozod qilishni kutmoqda.
V etcd - taftish/versiya qilingan kalitlar; «mod _ revision» bo’yicha navbat.
5. 5 Split-brain xatti-harakati
CP yondashuvi: kvorumsiz qulf olish mumkin emas - safety buzishdan ko’ra turish yaxshiroqdir.
AP-yondashuv: ajratilgan orollarda taraqqiyot mumkin → fencing kerak.
6) Yetakchilik (leader election)
etcd/ZK - «lider» eksklyuziv epemer kaliti; qolganlari o’zgartirish uchun imzolangan.
Rahbar heartbeats yozadi; yo’qotish - qayta saylanish.
Rahbarning barcha operatsiyalarini fencing token (davr/taftish raqami) bilan kuzatib boring.
7) Xatolar va ularni qayta ishlash
Mijoz qulfni oldi, lekin ishlashdan oldin krash → normalar, hech kim zarar ko’rmaydi; TTL/sessiya bo’shatiladi.
Qulf ish oʻrtasida tugadi:- Majburiy watchdog: agar uzaytirish muvaffaqiyatsiz boʻlsa - tanqidiy seksiyani toʻxtatib, orqaga qaytish/kompensatsiya qilish.
- Hech qanday «keyin tugatish»: qulfsiz tanqidiy qismni davom ettirish mumkin emas.
Uzoq pauza (GC/stop-the-world) → uzaytirish amalga oshmadi, ikkinchisi qulfni oldi. Ish jarayoni egalik yoʻqolishini (keepalive) aniqlab, uni toʻxtatishi kerak.
8) Dedloklar, ustuvorliklar va inversiya
Taqsimlangan dunyoda dedloklar kamdan-kam uchraydi (odatda bitta qulf), lekin agar bir nechta qulflar bo’lsa, lock ordering tartibiga rioya qiling.
Ustuvorlik inversiyasi: past prioritetli egasi resursni yuqori prioritetlilar kutayotganda ushlab turadi. Yechimlar: TTL-limitlar, preemption (agar biznes ruxsat bersa), sharding resurs.
Ochlik: adolat uchun kutish navbatlaridan (ZK-tartib tugunlari) foydalaning.
9) Kuzatish
Metriklar:- `lock_acquire_total{status=ok|timeout|error}`
- `lock_hold_seconds{p50,p95,p99}`
- ’fencing _ token _ value’ (monotonlik)
- `lease_renew_fail_total`
- ’split _ brain _ prevented _ total’ (kvorum yoʻqligi sababli qancha urinishlar rad etildi)
- `preemptions_total`, `wait_queue_len`
- `lock_name`, `owner_id`, `token`, `ttl`, `attempt`, `wait_time_ms`, `path` (для ZK), `mod_revision` (etcd).
- «acquire → critical section → release» spanlari natija bilan.
- ’lease _ renew _ fail _ total’ oʻsishi.
- `lock_hold_seconds{p99}` > SLO.
- «Yetim» qulflar (heartbeatsiz).
- Shoshilinch kutish navbatlari.
10) Amaliy misollar
10. 1 Xavfsiz Redis-qulf bilan fencing (psevdo)
1. Tokenlar hisoblagichini ishonchli saqlash (masalan, Postgres/etcd).
2. Agar «SET NX PX» muvaffaqiyatli bo’lsa, tokenni o’qiymiz/inkrementlaymiz va resursdagi barcha o’zgarishlarni tokenni DB/servisda tekshirish bilan amalga oshiramiz.
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 (Go)
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 ZKda yetakchilik (Java, Curator)
java
LeaderSelector selector = new LeaderSelector(client, "/leaders/cron", listener);
selector. autoRequeue();
selector. start(); // listener. enterLeadership() с try-finally и heartbeat
10. 4 Postgres advisory lock (SQL + app)
sql
SELECT pg_try_advisory_lock(128765); -- attempt without blocking
-- if false --> return via backoff + jitter
11) Test-pleybuklar (Game Days)
Kvorumni yo’qotish: 1-2 ta etcd tugunini o’chirish → qulfni olishga urinish o’tmasligi kerak.
GC pauza/stop-the-world: egasining oqimini sun’iy ravishda to’xtatib turish → watchdog uzilganligini tekshirish.
Split-brain: qulf egasi va tomoni o’rtasidagi tarmoq bo’linishining emulyatsiyasi → yangi egasi yuqori fencing tokenini oladi, eskisi esa sink tomonidan rad etiladi.
Clock skew/drift: soatni egasidan olish (Redis/lease uchun) → toʻgʻrilik tokenlar/tekshirishlar bilan taʼminlanishiga ishonch hosil qilish.
Crash before release: jarayonning pasayishi → qulf TTL/sessiyadan ozod qilinadi.
12) Anti-patternlar
Tashqi manbaga kirishda fencingsiz toza TTL-qulf.
Toʻgʻrilik uchun lokal vaqtga tayanish (HLC/fencingsiz).
Qulflarni bitta Redis-master orqali feylover bilan muhitda tarqatish.
Cheksiz tanqidiy qism (TTL «asrlar uchun»).
«Begona» qulfni’owner _ id ’/token bilan solishtirmasdan olib tashlash.
Backoff + jitter → «bo’ron» urinishlari yo’qligi.
«Hamma narsaga» yagona global qal’a - mojarolar sumkasi; kalit bo’yicha sharding yaxshiroqdir.
13) Joriy etish chek-varaqasi
- Resurs turi aniqlandi va CAS/navbat/idempotentlik bilan shug’ullanish mumkinmi?
- Tanlangan mexanizm: etcd/ZK/Consul CP uchun; Redis/kesh - faqat fencing bilan.
- Amalga oshirildi:’owner _ id’, TTL + uzaytirish, watchdog, toʻgʻri unlock.
- Tashqi resurs fencing tokenini tekshiradi.
- Etakchilik va jinoyatchilik strategiyasi mavjud.
- Metriklar, alertlar, tokenlar va taftishlarning logotiplari sozlangan.
- backoff + jitter va acquire taymautlari mavjud.
- Oʻyin kunlari: kvorum, split-brain, GC pauzalari, clock skew.
- Bir nechta qulflarni olish tartibi hujjatlari (agar talab qilinsa).
- Buzilish rejasi (brownout): qulf mavjud boʻlmaganda nima qilish kerak.
14) FAQ
Q: Redis-qulf’SET NX PX’yetarlimi?
A: Agar resurs fencing tokenni tekshirsa. Aks holda, tarmoq bo’linishida ikkita egasi bo’lishi mumkin.
Q: «Andoza» nimani tanlash kerak?
A: Qat’iy kafolatlar uchun - etcd/ZooKeeper/Consul (CP). Bitta DB ichida oson vazifalar uchun - advisory locks Postgres. Redis - faqat fencing bilan.
Q: Qanday TTL qo’yish kerak?
A:’TTL ≥ p99 × 2’tanqidiy qismining davomiyligi va «zombi» ni tezda tozalash uchun etarlicha qisqa. Uzaytirish - har bir’TTL/3’.
Q: Ochlikdan qanday qochish mumkin?
A: Tartib bo’yicha kutish navbati (ZK sequential) yoki fairness-algoritm; urinishlar limiti va adolatli rejalashtirish.
Q: Vaqt sinxronlashuvi kerakmi?
A: To’g’ri bo’lish uchun - yo’q (fencing ishlating). Operatsion bashorat qilish uchun - ha (NTP/PTP), lekin qulf mantig’ida wall-clockga tayanmang.
15) Yakunlar
Ishonchli taqsimlangan blokirovkalar lease + keepalive bilan kvorumli storlarda (etcd/ZK/Consul) quriladi va o’zgaruvchan resurs darajasida fencing token albatta to’ldiriladi. To’siqsiz har qanday TTL/Redis-yondashuvlar - split-breyn xavfi. Avval kauzallik va idempotentlik haqida o’ylang, ularsiz mumkin bo’lmagan joylarda qulflashdan foydalaning, o’lchang, sinov rejimlarini sinab ko’ring - va sizning «tanqidiy bo’limlaringiz» hodisalar soni bo’yicha emas, balki ma’nosi bo’yicha tanqidiy bo’lib qoladi.