GH GambleHub

Blocchi distribuiti

1) Perché (e quando) sono necessari blocchi distribuiti

Il blocco distribuito è un meccanismo che garantisce l'interscambio di una sezione critica tra più nodi di cluster. Attività tipiche:
  • Leadership (leader election) per l'attività di fondo/sheduler.
  • Limitazione dell'esecutore unico su una risorsa condivisa (spostamento dei file, migrazione dello schema, pagamento esclusivo).
  • Elaborazione sequenziale di un aggregato (wallet/order) se non è possibile ottenere un'idempotazione o un'organizzazione diversa.
Quando è meglio non usare la serratura:
  • Se è possibile creare un upsert idempotente, un CAS (compare-and-set) o una coda di chiave (per-key ordering).
  • Se la risorsa consente operazioni di switch (CRDT, contatori).
  • Se il problema viene risolto con una transazione in un unico archivio.

2) Modello di minacce e proprietà

Guasti e difficoltà:
  • Rete: ritardi, separazione, perdita di pacchetti.
  • Processi: pausa GC, stop-the-world, crash dopo aver preso la serratura.
  • Tempo: la deriva dell'orologio e lo spostamento spezzano gli approcci TTL.
  • «Zombie» dopo la rete potrebbe pensare di possedere ancora la serratura.
Proprietà desiderate:
  • Protezione: non più di un proprietario valido (safety).
  • Vivibilità: la serratura viene liberata in caso di guasto del proprietario (liveness).
  • Giustizia, non c'è fame.
  • Indipendenza dall'orologio: la correttezza non dipende da wall-clock (o compensato da fencing tokens).

3) Modelli di base

3. 1 Lease (castello d'affitto)

La serratura viene rilasciata con TTL. Il proprietario deve estenderlo fino alla scadenza (heartbeat/keepalive).

Il lato positivo è l'autocontrollo del crash.
Rischi: se il proprietario è bloccato e continua a lavorare, ma ha perso il rinnovo, potrebbe avere un doppio possesso.

3. 2 Fencing token (token della recinzione)

Ogni volta che viene catturato, viene dato un numero in crescita monotona. I consumatori della risorsa (database, coda, file storage) controllano il token e rifiutano le operazioni con il vecchio numero.
Ciò è fondamentale per TTL/lease e per le divise di rete: protegge dal proprietario «vecchio».

3. 3 serrature quorum (sistemi CC)

Utilizzano il consenso distribuito (Raft/Paxos; ), la voce è collegata a un punto di consenso. Non c'è uno split-breen nella maggior parte dei nodi.

Inoltre, una forte garanzia di sicurezza.
Meno: sensibilità al quorum (la sua perdita di vitalità zoppica).

3. 4 serrature PA (in-memory/cache + replica)

Ad esempio, un cluster Redis. Elevata disponibilità e velocità, ma senza garanzia di sicurezza per le divise di rete. Richiedono la fincing sul lato sink.

4) Piattaforme e pattern

4. 1 etcd/ ZooKeeper/Consul (raccomandato per strong locks)

Nodi effimeri (ZK) o sessioni/leases (etcd) - La chiave esiste finché la sessione è viva.
Sessione keepalive; La perdita del quorum è scaduta. Il castello è libero.
Nodi ordinali (ZK'EPHEMERAL _ SEQUENTIAL ') per la coda di attesa viene eseguita equità.

Sketch su 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 (con attenzione)

Classico: 'SET key value NX PX ttl'.

Problemi:
  • La replica/feelover può consentire ai proprietari simultanei.
  • Redlock da più istanze riduce il rischio ma non elimina; È controverso in ambienti con una rete non affidabile.

È più sicuro utilizzare Redis come uno strato di coordinatore veloce, ma sempre integrare il fencing token nella risorsa di destinazione.

Esempio (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 serrature BD

PostgreSQL advisory locks: lock all'interno del cluster Postges (processo/sessione).
È bello avere tutte le sezioni critiche in un unico database.

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

4. 4 Serrature di file/cloud

S3/GCS + metadato oggetto del vassoio con condizioni «If-Match» (ETag) è essenzialmente CAS.
Adatto per Becap/Migrazioni.

5) Design di una serratura sicura

5. 1 Identità del proprietario

Memorizza «owner _ id» (nodo # processo # pid # start _ time) + tocco casuale da comprimere con unlock.
Un nuovo unlock non deve togliere la serratura di qualcun altro.

5. 2 TTL e estensione

TTL <T _ fail _ detect (tempo di rilevamento del guasto) e ≥ p99 per la sezione critica x riserva.
L'estensione è periodica (ad esempio, ogni «TTL/3»), con deadline.

5. 3 Fencing token sul nastro

La sezione che modifica la risorsa esterna deve trasferire «fencing _ token».

Sink (database/cache/archivio) memorizza last _ token e rifiuta meno:
sql
UPDATE wallet
SET balance = balance +:delta, last_token =:token
WHERE id =:id AND:token > last_token;

5. 4 Attesa e equità

In ZK - 'EPHEMERAL _ SEQUENTIAL', e osservatori: il cliente attende il rilascio del predecessore più vicino.
In etcd - chiavi con revisione/versioning; La priorità è «med _ revision».

5. 5 Comportamento split-brain

Approccio CAP: senza quorum non si può prendere una serratura - meglio rimanere in piedi che rompere la safety.
Approccio AP: è possibile fare progressi nelle isole divise.

6) Leadership (leader election)

In etcd/ZK - «leader» è una chiave epemica esclusiva; gli altri sono firmati per le modifiche.
Il leader scrive heartbeats; La perdita è la rielezione.
Tutte le operazioni del leader accompagnare il fencing token (numero di epoca/revisione).

7) Errori e loro elaborazione

Il cliente ha preso la serratura, ma il crash prima del lavoro delle norme non si farà male. TTL/sessione sarà rilasciato.

La serratura è scaduta:
  • È obbligatorio watchdog: se l'estensione non è corretta, interrompere la sezione critica e ritrattare/compensare.
  • Niente «finisci dopo», non puoi continuare con la sezione critica senza la serratura.

Una lunga pausa (GC/stop-the-world) il prolungamento non è avvenuto, un altro ha preso la serratura. Il flusso di lavoro deve rilevare la perdita di proprietà (canale keepalive) e interrompere.

8) Deadlock, priorità e inversione

I dedlocchi nel mondo distribuito sono rari (la serratura è solitamente una), ma se ci sono più serrature, attenersi a un unico ordine di prelievo (lock ordering).
Inversione di priorità: il proprietario a bassa priorità mantiene la risorsa mentre i proprietari ad alta priorità attendono. Soluzioni: limiti TTL, preemption (se l'azienda lo permette), risorse sharding.
Digestione: utilizzare le code di attesa (nodi d'ordine ZK) per equità.

9) Osservabilità

Metriche:
  • `lock_acquire_total{status=ok|timeout|error}`
  • `lock_hold_seconds{p50,p95,p99}`
  • «fencing _ token _ value» (monotonia)
  • `lease_renew_fail_total`
  • «split _ brain _ prevented _ total» (numero di tentativi negati a causa della mancanza del quorum)
  • `preemptions_total`, `wait_queue_len`
Logi/tracking:
  • `lock_name`, `owner_id`, `token`, `ttl`, `attempt`, `wait_time_ms`, `path` (для ZK), `mod_revision` (etcd).
  • Span'aquire ', sezione critica «release», con il risultato.
Alert:
  • Altezza di lease _ renew _ fail _ total.
  • `lock_hold_seconds{p99}` > SLO.
  • Serrature orfane (senza heartbeat).
  • Code d'attesa gonfie.

10) Esempi pratici

10. 1 Sicuro Retis-serratura con fencing (pseudo)

1. Memorizziamo il contatore di token in uno store sicuro (ad esempio Postges/etcd).
2. Con il successo di SET NX PX, leggiamo/incrementiamo il token e tutte le modifiche apportate alla risorsa vengono eseguite con la verifica del token nel database/servizio.

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 in ZK (Java, Curator)

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

10. 4 Postges advisory lock con deadline (SQL + app)

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

11) Test playbook (Game Days)

Perdita del quorum: disattiva 1-2 nodi etcd. Il tentativo di togliere la serratura deve non passare.
GC-pausa/stop-the-world - Ritardare artificialmente il flusso del proprietario di controllare che watchdog interrompe il lavoro.
Split-brain: emulazione della divisione in rete tra il proprietario e lo store della serratura, il nuovo proprietario ottiene una fencing token più alta, il vecchio è rifiutato dal sink.
Clock skew/draft - Togliere l'orologio dal proprietario (per Redis/lease) per assicurarsi che i token/controlli forniscano correttezza.
Crash before release - Il crollo del processo viene rilasciato in TTL/sessione.

12) Anti-pattern

Serratura netta TTL senza fincing quando si accede a una risorsa esterna.
Affidarsi al tempo locale per la correttezza (senza HLC/fencing).
Distribuzione di serrature attraverso una procedura guidata Redis in un ambiente con feelover e senza conferma delle repliche.
Sezione critica infinita (TTL «secoli»).
Rimuove il lucchetto «estraneo» senza comprimere «owner _ id »/token.
L'assenza di backoff + jitter è una tempesta di tentativi.
Un unico castello globale è un sacco di conflitti; Lo sharding è meglio della chiave.

13) Assegno-foglio di implementazione

  • È stato definito il tipo di risorsa e se è possibile fare clic su CAS/coda/idimpotenza.
  • Il meccanismo selezionato è etcd/ZK/Consul; Redis/cache - solo con fencing.
  • Implementato: 'owner _ id', TTL + estensione, watchdog, unlock corretto.
  • La risorsa esterna controlla il fencing token (monotonia).
  • C'è una strategia di leadership e failover.
  • Le metriche, gli alert, la logica dei token e le revisioni sono configurati.
  • Sono previsti backoff + jitter e timeout su acquire.
  • Sono stati eseguiti game days: quorum, split-brain, pause GC, clock skew.
  • Documentazione relativa al prelievo di più serrature (se necessario).
  • Piano di degrado (brownout): cosa fare quando la serratura non è disponibile.

14) FAQ

Q: Il lucchetto Redis «SET NX PX» è sufficiente?
A: Solo se la risorsa verifica il fencing token. In caso contrario, possono essere condivisi due proprietari.

Q: Che scelta è predefinita?
A: Per le severe garanzie, etcd/ZooKeeper/Consul. Per operazioni facili all'interno di un unico database - advisory locks Postges. Redis è solo con la fincing.

Q: Quale TTL mettere?
A: «TTL p99 durata sezione critica x 2» e abbastanza breve per una rapida pulizia «zombie». Estensione: ogni «TTL/3».

Come evitare la fame?
A: Coda di attesa ordine (ZK sequential) o fairness; un limite di tentativi e una pianificazione equa.

C'è bisogno di sincronizzare il tempo?
A: Non per correttezza (usa fencing). Per la prevedibilità operativa sì (NTP/PTP), ma non affidatevi al wall-clock nella logica della serratura.

15) Riepilogo

Blocchi distribuiti affidabili sono costruiti su store quorum (etcd/ZK/Consul) con lease + keepalive, e sono necessariamente completati da fencing token a livello di risorsa modificabile. Qualsiasi approccio TTL/Redis senza recinzione è il rischio di split-breen. Pensate prima alla causalità e all'idampotenza, usate i blocchi dove non è possibile, misurate, testate le modalità di guasto - e le vostre «sezioni critiche» rimarranno critiche solo in termini di senso e non in termini di incidenti.

Contact

Mettiti in contatto

Scrivici per qualsiasi domanda o richiesta di supporto.Siamo sempre pronti ad aiutarti!

Avvia integrazione

L’Email è obbligatoria. Telegram o WhatsApp — opzionali.

Il tuo nome opzionale
Email opzionale
Oggetto opzionale
Messaggio opzionale
Telegram opzionale
@
Se indichi Telegram — ti risponderemo anche lì, oltre che via Email.
WhatsApp opzionale
Formato: +prefisso internazionale e numero (ad es. +39XXXXXXXXX).

Cliccando sul pulsante, acconsenti al trattamento dei dati.