GH GambleHub

Verrous distribués

1) Pourquoi (et quand) des verrous distribués sont nécessaires

Le verrouillage distribué est un mécanisme qui garantit l'exclusion mutuelle de la section critique entre plusieurs nœuds de la grappe. Tâches types :
  • Leadership (election leader) pour la tâche de fond/sheduleur.
  • Limiter le seul intervenant sur la ressource partagée (déplacement de fichiers, migration de schéma, étape de paiement exclusive).
  • Traitement séquentiel de l'agrégat (wallet/order) si vous ne pouvez pas obtenir l'idempotence/ordre autrement.
Quand il est préférable de ne pas utiliser le château :
  • Si vous pouvez faire un upsert idempotent, CAS (compare-and-set) ou une file d'attente par clé (per-key ordering).
  • Si la ressource permet des opérations commutatives (CRDT, compteurs).
  • Si le problème est résolu par une transaction dans le même magasin.

2) Modèle de menace et propriétés

Refus et complexité :
  • Réseau : retards, partition, perte de paquets.
  • Processus : Pause GC, stop-the-world, crash après la prise du château.
  • Temps : la dérive de l'horloge et le décalage brisent les approches TTL.
  • Réoccupation : le processus « zombie » après le réseau peut penser qu'il possède encore le château.
Propriétés souhaitées :
  • Sécurité : pas plus d'un propriétaire valide (sécurité).
  • Survie : le château est libéré en cas de défaillance du propriétaire (liveness).
  • Justice : il n'y a pas de jeûne.
  • Indépendance par rapport à l'horloge : l'exactitude ne dépend pas de l'horloge murale (ou est compensée par des jetons de fencing).

3) Modèles principaux

3. 1 Lease (château de location)

La serrure est délivrée avec le TTL. Le propriétaire est tenu de le renouveler avant l'expiration (heartbeat/keepalive).

Avantages : Auto-entretien au crash.
Risques : si le propriétaire « zavis » et continue à travailler, mais a perdu le renouvellement, il peut y avoir une double possession.

3. 2 jetons Fencing (jeton de clôture)

À chaque capture réussie, un numéro de croissance monotone est émis. Les utilisateurs de la ressource (OBD, file d'attente, stockage de fichiers) vérifient le token et rejettent les opérations avec l'ancien numéro.
C'est essentiel dans le TTL/lease et les divisions réseau - protège contre le « vieux » propriétaire.

3. 3 verrous quorum (systèmes CP)

Ils utilisent un consensus distribué (Raft/Paxos ; etcd/ZooKeeper/Consul), l'entrée est liée à la logique de consensus → il n'y a pas de split-brein dans la plupart des nœuds.

Plus : de solides garanties de sécurité.
Moins : sensibilité au quorum (à sa perte, la survie est chromeuse).

3. 4 verrous AP (in-memory/cache + réplication)

Par exemple, un cluster Redis. Haute disponibilité et vitesse, mais sans garanties de sécurité strictes pour les séparations réseau. Nécessite un fencing sur le côté du bleu.

4) Plates-formes et modèles

4. 1 etcd/ZooKeeper/Consul (recommandé pour strong locks)

Nœuds éphémères (ZK) ou sessions/leases (etcd) : la clé existe tant que la session est en vie.
Keepalive de session ; la perte de quorum → session expire → le château est libéré.
Les nœuds d'ordre (ZK 'EPHEMERAL _ SEQUENTIAL') pour la file d'attente → justice.

Croquis sur etcd (Go) :
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 (avec soin)

Le classique est 'SET key value NX PX ttl'.

Problèmes :
  • La réplication/faussaire peut autoriser des propriétaires simultanés.
  • Redlock de plusieurs instances réduit le risque, mais ne l'élimine pas ; controversé dans les environnements avec un réseau peu fiable.

Il est plus sûr d'appliquer Redis en tant que couche de coordination rapide, mais toujours compléter le fencing token dans la ressource cible.

Exemple (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 verrous OBD

PostgreSQL advisory locks : lock in the Postgres cluster (processus/session).
C'est bien quand toutes les sections critiques sont déjà dans la même base de données.

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

4. 4 Serrures de fichiers/cloud

S3/GCS + métadonnées d'objet avec les conditions « If-Match » (ETag) → essentiellement CAS.
Convient pour les backups/migrations.

5) Conception de la serrure de sécurité

5. 1 Identité du propriétaire

Stockez 'owner _ id' (nœud # processus # pid # start _ time) + un jeton aléatoire pour le rapprochement à unlock.
Il ne faut pas enlever la serrure de quelqu'un d'autre.

5. 2 TTL et renouvellement

TTL <T_fail_detect (temps de détection de panne) et ≥ p99 de fonctionnement de la section critique × stock.
Renouvellement - périodiquement (par exemple, tous les 'TTL/3'), avec deadline.

5. 3 jetons Fencing sur le bleu

La section qui modifie la ressource externe doit transmettre 'fencing _ token'.

Sink (OBD/cache/stockage) stocke 'last _ token' et rejette les plus petits :
sql
UPDATE wallet
SET balance = balance +:delta, last_token =:token
WHERE id =:id AND:token > last_token;

5. 4 La file d'attente et la justice

Dans ZK - 'EPHEMERAL _ SEQUENTIAL' et les observateurs : le client attend la libération du prédécesseur le plus proche.
Etcd - clés avec révision/versioning ; priorité par 'mod _ revision'.

5. 5 Comportement avec split-brain

Approche CP : sans quorum, vous ne pouvez pas prendre la serrure - mieux vaut rester inactif que casser la sécurité.
Approche AP : des progrès sont permis dans les îles divisées → le fencing est nécessaire.

6) Leadership (leader election)

Dans etcd/ZK - le « leader » est une clé épémère exclusive ; les autres sont signés pour les changements.
Le leader écrit heartbeats ; la perte est la réélection.
Toutes les opérations du leader sont accompagnées par fencing token (numéro d'époque/révision).

7) Erreurs et leur traitement

Le client a pris le château, mais crash avant le travail des normes →, personne ne sera blessé ; TTL/session sera libérée.

La serrure a expiré au milieu du travail :
  • Il est obligatoire de watchdog : si la prolongation échoue - interrompre la section critique et reculer/compenser.
  • Pas de « finir plus tard » : sans serrure, la section critique ne peut pas continuer.

La longue pause (GC/stop-the-world) → la prolongation n'a pas eu lieu, l'autre a pris le château. Le flux de travail doit détecter la perte de propriété (canal keepalive) et l'interrompre.

8) Dédeloques, priorités et inversion

Les dédlocks dans le monde distribué sont rares (le château est généralement un), mais si les verrous sont multiples - respectez un seul ordre de prise (lock ordering).
Inversion des priorités : un propriétaire peu prioritaire garde la ressource pendant que les priorités élevées attendent. Solutions : limites TTL, préemption (si l'entreprise le permet), partage de la ressource.
Jeûne : utilisez les files d'attente (nœuds ZK-sous-ordre) pour la justice.

9) Observabilité

Métriques :
  • `lock_acquire_total{status=ok|timeout|error}`
  • `lock_hold_seconds{p50,p95,p99}`
  • 'Fencing _ token _ value '(monotonie)
  • `lease_renew_fail_total`
  • 'split _ brain _ prevented _ total '(nombre de tentatives refusées faute de quorum)
  • `preemptions_total`, `wait_queue_len`
Logi/tracing :
  • `lock_name`, `owner_id`, `token`, `ttl`, `attempt`, `wait_time_ms`, `path` (для ZK), `mod_revision` (etcd).
  • Spans « acquire → critical section → release » avec le résultat.
Alert :
  • Taille 'lease _ renew _ fail _ total'.
  • `lock_hold_seconds{p99}` > SLO.
  • Châteaux « orphelins » (sans heartbeat).
  • Files d'attente gonflées.

10) Exemples pratiques

10. 1 serrure Redis sécurisée avec fencing (pseudo)

1. Nous stockons le compteur de jetons dans une store fiable (par exemple Postgres/etcd).
2. Si 'SET NX PX' réussit, nous lisons/incrémentons le token et faisons toutes les modifications de la ressource avec la vérification du token dans la base de données/service.

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 Leadership en ZK (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 avec dedline (SQL + app)

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

11) Test-playbooks (Game Days)

Perte de quorum : Désactiver 1-2 nœuds etcd → essayer de prendre le verrou ne doit pas passer.
GC-pause/stop-the-world : retarder artificiellement le flux du propriétaire → vérifier que le watchdog interrompt le travail.
Split-brain : émulation de la séparation réseau entre le propriétaire et le gardien du château → le nouveau propriétaire obtient un plus haut fencing token, l'ancien - rejeté par le bleu.
Clock skew/drift : éloignez l'horloge du propriétaire (pour Redis/lease) → assurez-vous que l'exactitude est assurée par les tokens/contrôles.
Crash before release : la chute du processus de → du verrou est libérée par TTL/session.

12) Anti-modèles

Une serrure TTL propre sans fencing lorsque vous accédez à une ressource externe.
Compter sur l'heure locale pour être correct (sans HLC/fencing).
Distribution de serrures à travers un seul maître Redis dans un environnement avec faussaire et sans confirmation de répliques.
Section critique infinie (TTL « depuis des siècles »).
Supprime le verrou « étranger » sans le rapprochement 'owner _ id '/token.
L'absence de backoff + jitter → la « tempête » des tentatives.
Une seule serrure mondiale est un sac de conflits ; Le sharding par clé est mieux.

13) Chèque de mise en œuvre

  • Le type de ressource est défini et peut-on se contenter de CAS/file d'attente/idempotence.
  • Mécanisme choisi : etcd/ZK/Consul pour le CP ; Redis/cache - avec fencing uniquement.
  • Réalisé par : 'owner _ id', TTL + extension, watchdog, correct unlock.
  • La ressource externe vérifie le fencing token (monotonie).
  • Il y a une stratégie de leadership et d'échec.
  • Les métriques, les alertes, le logage des tokens et les révisions sont configurés.
  • Backoff + jitter et les temps d'attente sont fournis.
  • Les journées de jeu ont eu lieu : quorum, split-brain, GC-pause, clock skew.
  • Documentation de l'ordre de prise de plusieurs verrous (si nécessaire).
  • Plan de dégradation (brownout) : que faire en cas d'indisponibilité du château.

14) FAQ

Q : La serrure Redis 'SET NX PX' est-elle suffisante ?
R : Seulement si la ressource vérifie les token de fencing. Sinon, deux propriétaires sont possibles lors de la séparation réseau.

Q : Que choisir par défaut ?
A : Pour des garanties strictes - etcd/ZooKeeper/Consul (CP). Pour les tâches faciles à l'intérieur d'une seule base de données - advisory locks Postgres. Redis n'est qu'avec fencing.

Q : Quel TTL mettre ?
A : 'TTL ≥ p99 durée de la section critique × 2' et assez courte pour nettoyer rapidement les « zombies ». Renouvellement - tous les 'TTL/3'.

Q : Comment éviter le jeûne ?
A : File d'attente dans l'ordre (ZK sequential) ou algorithme fairness ; limitation des tentatives et planification équitable.

Q : Ai-je besoin d'une synchronisation temporelle ?
R : Pour être correct - non (utilisez fencing). Pour la prévisibilité opérationnelle - oui (NTP/PTP), mais ne comptez pas sur le wall-clock dans la logique du château.

15) Résultats

Les verrous distribués robustes sont construits sur des caissons de quorum (etcd/ZK/Consul) avec lease + keepalive, et doivent être complétés au niveau de la ressource modifiable. Toute approche TTL/Redis sans clôture est un risque de split-brain. Pensez d'abord à la causalité et à l'idempotence, utilisez les verrous là où vous ne pouvez pas, mesurez, testez les modes de défaillance - et vos « sections critiques » resteront critiques seulement dans le sens et non dans le nombre d'incidents.

Contact

Prendre contact

Contactez-nous pour toute question ou demande d’assistance.Nous sommes toujours prêts à vous aider !

Commencer l’intégration

L’Email est obligatoire. Telegram ou WhatsApp — optionnels.

Votre nom optionnel
Email optionnel
Objet optionnel
Message optionnel
Telegram optionnel
@
Si vous indiquez Telegram — nous vous répondrons aussi là-bas.
WhatsApp optionnel
Format : +code pays et numéro (ex. +33XXXXXXXXX).

En cliquant sur ce bouton, vous acceptez le traitement de vos données.