Questo articolo è un articolo speculare di traduzione automatica, clicca qui per saltare all'articolo originale.

Vista: 10939|Risposta: 1

Diversi modi per usare le serrature distribuite (redis, zookeeper, database)

[Copiato link]
Pubblicato su 30/08/2018 15:04:32 | | | |
D: Un server di servizio, un database, operazione: consulta il saldo corrente dell'utente, detrai il 3% del saldo attuale come commissione di gestione

sincronizzato
serratura
Blocco DB

D: Due server di servizio, un database, operazione: consultare il saldo attuale dell'utente, detrarre il 3% del saldo attuale come commissione di gestione
Blocchi distribuiti

Che tipo di serratura distribuita ci serve?
Può garantire che in un cluster di applicazioni distribuito, lo stesso metodo possa essere eseguito solo da un thread su una stessa macchina contemporaneamente.

Se questa chiusa è una chiusa reentrante (evitare blocchi)

Questa serratura è migliore per essere bloccante (considera se la vuoi in base alle esigenze della tua attività).

Questa serratura è meglio per essere una serratura equa (considera se la vuoi o meno in base alle esigenze aziendali)

Sono disponibili funzioni di acquisizione e rilascio del blocco

Le prestazioni dei blocchi di acquisizione e rilascio sono migliori

1. Serrature distribuite basate su database

Locks distribuiti basati su implementazioni basate su tabelle

Quando vogliamo bloccare un metodo, eseguiamo il seguente SQL:
inserire nel metodoLock(method_name,desc) valori ('method_name','desc')
Poiché abbiamo imposto un vincolo di unicità sul method_name, se vengono inviate più richieste contemporaneamente al database, il database garantirà che solo un'operazione possa avere successo, allora possiamo assumere che il thread che ha ottenuto con successo il metodo si blocchi e possa eseguire il corpo del contenuto.

Quando il metodo viene eseguito, se vuoi liberare il blocco, devi eseguire il seguente Sql:
elimina da methodLock dove method_name ='method_name'

Questa semplice implementazione sopra presenta i seguenti problemi:

  • Questo blocco dipende dalla disponibilità del database, che è un singolo punto e farà sì che il sistema aziendale non sia disponibile una volta che il database viene bloccato.
  • Questo lock non ha tempi di scadenza e, una volta fallita l'operazione di sblocco, il record del lock rimarrà nel database e gli altri thread non potranno più ottenere il lock.
  • Questo blocco può essere non bloccante solo perché l'operazione di inserimento dei dati riporterà direttamente un errore una volta fallita l'inserimento. I thread che non acquisiscono lock non entreranno nella coda e dovranno attivare nuovamente l'operazione di acquisizione lock per ottenere nuovamente il lock.
  • La serratura non è reentrante e la stessa filettatura non può riprenderla finché non viene rilasciata. Perché i dati contenuti nei dati esistono già.
  • Questa serratura è una serratura slea, e tutti i fili in attesa della serratura competono per la serratura per fortuna.


Naturalmente, possiamo anche risolvere i problemi sopra elencati in altri modi.

  • Il database è un singolo punto? Costruisci due database e i dati saranno sincronizzati in entrambe le direzioni. Una volta riattaccato, passa rapidamente alla libreria di backup.
  • Nessun tempo di scadenza? Fai semplicemente un compito programmato per pulire i dati di timeout nel database a intervalli regolari.
  • Non bloccanti? Fai un loop di tempo finché l'inserimento non ha successo e poi torna il successo.
  • Non reentrante? Aggiungi un campo alla tabella del database per registrare le informazioni dell'host e dei thread della macchina che attualmente riceve il lock, poi la prossima volta che ottieni il lock, consulta prima il database; se le informazioni host e dei thread della macchina attuale si trovano nel database, puoi assegnare direttamente il lock a lui.
  • Ingiusto? Crea un'altra tabella intermedia per registrare tutti i thread in attesa del lock, ordinandoli in base al momento di creazione, e solo il primo creato può acquisire il lock


Blocchi distribuiti basati su blocchi esclusivi

Oltre ad aggiungere e cancellare i record nella tabella dati, i lock distribuiti possono essere implementati anche con l'aiuto dei lock forniti con i dati.

Usiamo anche la tabella del database che abbiamo appena creato. I lock distribuiti possono essere implementati tramite lock esclusivi nei database. Il motore InnoDB basato su MySQL può utilizzare i seguenti metodi per implementare operazioni di lock-up:

Se aggiungi per l'aggiornamento dopo la query statement, il database aggiungerà un blocco esclusivo alla tabella del database durante il processo di interrogazione. Quando un blocco esclusivo viene aggiunto a un record, altri thread non possono più aggiungere un blocco esclusivo al record su quella linea.

Possiamo pensare che il thread che ottiene il lock esclusivo possa ottenere il lock distribuito, e quando il lock viene ottenuto, la logica di business del metodo può essere eseguita e poi sbloccata tramite i seguenti metodi:

sblocco del vuoto pubblico(){ connection.commit(); }

tramite connection.commit(); operazione per aprire la serratura.

Questo metodo può risolvere efficacemente i problemi sopra menzionati riguardo all'impossibilità di aprire la serratura e bloccarla.

Bloccare le serrature? L'istruzione for update ritorna immediatamente dopo l'esecuzione riuscita e rimane bloccata fino al successo.

Il servizio è caduto dopo il lock, non può essere rilasciato? In questo modo, il database rilascia il blocco da solo dopo che il servizio è stato interrotto.

Tuttavia, non risolve ancora direttamente il problema del singolo punto del database, della rientranza e del fair locking.

Per riassumere il modo di utilizzare il database per implementare i lock distribuiti, entrambi basati su una tabella nel database, uno consiste nel determinare se esiste un lock tramite l'esistenza dei record nella tabella, e l'altro è implementare lock distribuiti tramite il lock esclusivo del database.

Vantaggi dei database con blocco distribuito

Direttamente con l'aiuto del database, è facile da capire.

Svantaggi nell'implementare locks distribuiti nei database

Ci saranno vari problemi e l'intera soluzione diventerà sempre più complessa nel processo di risoluzione.

Gestire il database richiede un certo sovraccarico e devono essere considerati problemi di prestazioni.

2. Locks distribuiti basati sulla cache

Rispetto alla soluzione di blocco distribuito basata su database, l'implementazione basata sulla cache avrà prestazioni migliori.

Attualmente esistono molti prodotti di cache maturi, tra cui Redis, memcached, ecc. Qui prendiamo Redis come esempio per analizzare lo schema dell'uso della cache per implementare i lock distribuiti.

Ci sono molti articoli correlati su Internet riguardanti l'implementazione di blocchi distribuiti basati su Redis, e il metodo principale di implementazione è l'uso del metodo Jedis.setNX.

Ci sono anche diversi problemi con l'implementazione sopra citata:

1. Problema a punto singolo.

2. Questo lock non ha tempi di scadenza, una volta che l'operazione di sblocco fallisce, il record del lock rimane sempre in redis e gli altri thread non possono più ottenere il lock.

3. Questo blocco può essere solo non bloccante e tornerà direttamente indipendentemente dal successo o fallimento.

4. Questa serratura non è reentrante, dopo che un filo ha ottenuto la serratura, non può ottenere nuovamente la serratura prima di rilasciarla, perché la chiave usata esiste già in redis. le operazioni setNX non possono più essere eseguite.

5. Questo blocco è iniusto, tutti i thread in attesa iniziano le operazioni setNX contemporaneamente e i thread fortunati possono ottenere il lock.

Naturalmente, ci sono anche modi per risolverlo.

  • Oggigiorno, i servizi di cache tradizionali supportano il deployment di cluster per risolvere problemi a singolo punto tramite clustering.
  • Nessun tempo di scadenza? Il metodo setExpire di redis supporta il tempo di scadenza in ingresso e i dati vengono automaticamente cancellati dopo che il tempo è raggiunto.
  • Non bloccanti? mentre veniva eseguito ripetutamente.
  • Non è possibile rientrare? Dopo che un thread acquisisce il lock, salva le informazioni attuali dell'host e del thread, e verifica se sei il proprietario del lock corrente prima di ottenerlo la prossima volta.
  • Ingiusto? Metti tutti i thread in attesa in coda prima che un thread acquisisca un blocco, e poi acquisisci il blocco secondo il sistema first-in, first-out.


La politica di sincronizzazione del cluster Redis richiede tempo, ed è possibile che il thread A venga bloccato dopo aver impostato con successo NX, ma questo valore non è stato aggiornato al server dove il thread B esegue setNX, il che causerà problemi di concorrenza.

Salvatore Sanfilippo, autore di redis, propose l'algoritmo Redlock, che implementa una gestione distribuita dei lock (DLM) più sicura e affidabile di un singolo nodo.

L'algoritmo Redlock assume che ci siano N nodi redis indipendenti tra loro, generalmente impostati su N=5, e questi N nodi girano su macchine diverse per mantenere l'indipendenza fisica.

I passaggi dell'algoritmo sono i seguenti:

1. Il cliente ottiene il tempo corrente in millisecondi.
2. Il client cerca di ottenere il lock di N nodi, (ogni nodo ottiene il lock nello stesso modo del lock cache menzionato prima), e N nodi ottengono il lock con la stessa chiave e valore. Il client deve impostare il timeout di accesso all'interfaccia, e il timeout dell'interfaccia deve essere molto inferiore a quello del lock; ad esempio, il tempo di rilascio automatico del lock è di 10s, poi il timeout dell'interfaccia è impostato a circa 5-50ms. Questo ti permette di smettere il prima possibile quando accedi a un nodo redis dopo che è caduto, e riduce l'uso normale del blocco.
3. Il client calcola quanto tempo impiega per ottenere il lock, sottraendo il tempo ottenuto nel passo 1 con il tempo corrente; solo quando il client ottiene più di 3 nodi del lock e il tempo per acquisire il lock è inferiore al timeout del lock, il client ottiene il lock distribuito.
4. Il tempo che il cliente ha per acquisire il blocco è il tempo di timeout impostato meno il tempo impiegato per ottenere il blocco calcolato al passo 3.
5. Se il client non riesce a ottenere il blocco, il client eliminerà tutti i blocchi a turno.
Utilizzando l'algoritmo Redlock, è garantito che il servizio di blocco distribuito possa ancora funzionare quando si blocca fino a 2 nodi, il che migliora notevolmente la disponibilità rispetto al precedente blocco database e blocco cache.

Tuttavia, un esperto distribuito ha scritto un articolo intitolato "Come fare il blocco distribuito" mettendo in dubbio la correttezza di Redlock.

L'esperto ha menzionato che ci sono due aspetti da considerare quando si considerano serrature distribuite: prestazioni e correttezza.

Se usi un blocco distribuito ad alte prestazioni e non è richiesta la correttezza, allora l'uso di un lock cache è sufficiente.

Se usi una serratura distribuita altamente affidabile, allora devi considerare questioni di affidabilità molto rigorose. Il redlock, invece, non soddisfa la correttezza. Perché no? Gli esperti elencano diversi aspetti.

Oggigiorno, molti linguaggi di programmazione usano macchine virtuali con funzioni GC, in Full GC il programma interrompe l'elaborazione GC, a volte Full GC richiede molto tempo, e anche il programma ha qualche minuto di ritardo; l'articolo elenca l'esempio di HBase, HBase a volte GC per qualche minuto, il che fa scadere il contratto di locazione. Ad esempio, nella figura sottostante, il client 1 ottiene un lock ed è sul punto di elaborare una risorsa condivisa, e quando sta per elaborare una risorsa condivisa, il Full GC avviene fino alla scadenza del lock. In questo modo, il client 2 ottiene di nuovo il blocco e inizia a lavorare sulla risorsa condivisa. Quando il client 2 è in elaborazione, il client 1 completa la GC completa e inizia a elaborare le risorse condivise, così che entrambi i client elaborino risorse condivise.



Gli esperti hanno fornito una soluzione, come mostrato nella figura sotto: sembra che MVCC porti un token al lock, il token è il concetto di versione, ogni volta che il lock operativo viene completato, il token verrà aggiunto 1, porta il token quando si elaborano le risorse condivise, solo la versione specificata del token può gestire la risorsa condivisa.



Poi l'esperto ha anche detto che l'algoritmo si basa sull'ora locale, e che Redis si affida al metodo getTimeOfDay per ottenere l'ora invece che sull'orologio monotono quando gestisce la scadenza della chiave, il che porta anche a imprecisioni temporali. Ad esempio, in uno scenario, due client 1 e client 2 hanno 5 nodi redis (A, B, C, D ed E).

1. Il Client 1 acquisisce con successo il blocco da A, B e C e ottiene il timeout della rete del blocco da D ed E.
2. L'orologio del nodo C è impreciso, causando il timeout del blocco.
3. il client 2 acquisisce con successo il lock da C, D ed E, e ottiene il timeout della rete dei lock da A e B.
4. In questo modo, sia il client 1 che il client 2 ottengono un blocco.
Per riassumere i due punti che gli esperti dicono sull'indisponibilità di Redlock:

1. GC e altri scenari possono verificarsi in qualsiasi momento, causando l'acquisizione di un blocco al cliente, e il timeout di elaborazione fa sì che un altro client ottenga il blocco. Gli esperti hanno anche fornito una soluzione all'uso dei token auto-incrementanti.
2. L'algoritmo si basa sull'ora locale e l'orologio sarà impreciso, facendo sì che due client ottengano blocchi contemporaneamente.
Pertanto, la conclusione fornita dagli esperti è che Redlock può funzionare normalmente solo nell'intervallo di ritardo di rete limitato, nell'interruzione di programma limitata e nell'intervallo di errore di clock limitato, ma i confini di questi tre scenari non possono essere confermati, quindi gli esperti non raccomandano l'uso di Redlock. Per scenari con elevati requisiti di correttezza, gli esperti raccomandano Zookeeper, che sarà discusso più avanti utilizzando Zookeeper come serratura distribuita.

Risposta dell'autore di Redis

L'autore di Redis ha risposto scrivendo un blog dopo aver visto l'articolo dell'esperto. L'autore ringraziò educatamente l'esperto, poi espresse il suo disaccordo con il punto di vista dell'esperto.

Ho chiesto un'analisi nella specifica originale Redlock qui:http://redis.io/topics/distlock.Quindi grazie Martin. Tuttavia non sono d'accordo con l'analisi.


La discussione dell'autore di REDIS sull'uso dei token per risolvere il problema del timeout del blocco può essere riassunta nei seguenti cinque punti:

Punto 1, l'uso dei lock distribuiti generalmente è nel senso che non hai altro modo per controllare le risorse condivise, gli esperti usano i token per garantire l'elaborazione delle risorse condivise, quindi non c'è bisogno di lock distribuiti.
Punto 2: Per la generazione dei token, per garantire l'affidabilità dei token ottenuti da diversi client, il servizio che genera i token necessita ancora di lock distribuiti per garantire l'affidabilità del servizio.
Punto 3, per il modo in cui gli esperti dicono i token auto-incrementanti, l'autore di Redis ritiene che sia completamente inutile, ogni client può generare un uuid unico come token e impostare la risorsa condivisa in uno stato che solo il client con l'uuid può gestire, così che altri client non possano elaborare la risorsa condivisa finché il client che ottiene il lock non lo rilascia.
Come mostrato nella figura sopra, se il client del token 34 invia GC durante il processo di scrittura e fa sì che il blocco si scateni in timeout, un altro client può ottenere il blocco del token 35 e ricominciare a scrivere, causando un conflitto di lock. Pertanto, l'ordine dei token non può essere combinato con risorse condivise.
Punto 5, l'autore di Redis ritiene che nella maggior parte degli scenari i lock distribuiti vengano utilizzati per gestire problemi di aggiornamento in scenari non transazionali. L'autore dovrebbe intendere che ci sono alcuni scenari in cui è difficile combinare i token per gestire risorse condivise, quindi bisogna affidarsi ai blocchi per bloccare e processare le risorse.
Un altro problema dell'orologio di cui parlano gli esperti, gli autori di Redis forniscono anche una spiegazione. Se il tempo necessario per acquisire il lucchetto è troppo lungo e supera il tempo di scadenza predefinito del lucchetto, il cliente non può ottenere il lucchetto in quel momento e non saranno proposti esempi da parte degli esperti.

Sentimenti personali

Il primo problema che riassumo è che, dopo che un client ottiene un blocco distribuito, il lock può essere rilasciato dopo un timeout durante l'elaborazione del client. In precedenza, quando si parlava del timeout impostato dal blocco del database di 2 minuti, se un compito occupa un blocco d'ordine per più di 2 minuti, allora l'altro centro di trading può ottenere questo blocco d'ordine, così che i due centri possano elaborare lo stesso ordine contemporaneamente. In circostanze normali, il compito viene elaborato in pochi secondi, ma a volte, se il timeout impostato unendo una richiesta RPC è troppo lungo e ci sono più richieste di timeout in un task, quindi è probabile che il tempo di sblocco automatico venga superato. Se scriviamo in Java, potrebbe esserci Full GC nel mezzo, quindi dopo che il lock è stato sbloccato dopo il timeout del lock, il client non può percepirlo, il che è una cosa molto seria. Non credo che questo sia un problema del blocco in sé, finché qualsiasi blocco distribuito menzionato sopra ha le caratteristiche di rilascio del timeout, questo problema si verificherà. Se si utilizza la funzione di timeout del blocco, il client deve impostare il timeout e agire di conseguenza, invece di continuare a elaborare la risorsa condivisa. L'algoritmo di Redlock restituisce il tempo di blocco che il client può occupare dopo che il client ha acquisito il lock, e il client deve elaborare questo tempo per fermare il compito dopo tale tempo.

Il secondo problema è che gli esperti distribuiti non comprendono Redlock. Una caratteristica chiave di Redlock è che il tempo necessario per acquisire il blocco è il tempo totale in cui il blocco si attiva di default meno il tempo necessario per acquisire il blocco, quindi il tempo necessario per l'elaborazione dal client è relativo, indipendentemente dall'ora locale.

Da questo punto di vista, la correttezza di Redlock può essere ben garantita. Un'analisi attenta di Redlock, rispetto a Redis di un nodo, la caratteristica principale fornita da Redlock è una maggiore affidabilità, che è una caratteristica importante in alcuni scenari. Ma penso che Redlock abbia speso troppi soldi per ottenere affidabilità.

  • Innanzitutto, devono essere dispiegati 5 nodi per rendere Redlock più affidabile.
  • Poi devi richiedere 5 nodi per ottenere il lock, e tramite il metodo Future puoi prima richiedere 5 nodi contemporaneamente, e poi ottenere il risultato della risposta, il che può ridurre i tempi di risposta, ma richiede comunque più tempo rispetto a un lock-redis a nodo singolo.
  • Poi, poiché più di 3 dei 5 nodi devono essere ottenuti, può esserci un conflitto di blocco, cioè tutti hanno ottenuto 1-2 blocchi e, di conseguenza, nessuno può ottenere il blocco; questo problema, l'autore di Redis prende in prestito l'essenza dell'algoritmo a raft, attraverso la collisione a tempo casuale, il tempo di conflitto può essere notevolmente ridotto, ma questo problema non può essere evitato molto bene, specialmente quando il blocco viene acquisito per la prima volta, quindi il costo temporale per acquisire il blocco aumenta.
  • Se 2 dei 5 nodi sono fuori uso, la disponibilità del blocco sarà notevolmente ridotta; innanzitutto, bisogna aspettare che i risultati di questi due nodi caduti si scatenino prima di tornare al ritorno, e ci sono solo 3 nodi, e il client deve ottenere i blocchi di tutti e 3 per avere il blocco, il che è anch'esso più difficile.
  • Se esiste una partizione di rete, potrebbe esserci una situazione in cui il client non riuscirà mai a ottenere il lock.


Dopo aver analizzato così tante ragioni, penso che il punto più critico del problema di Redlock sia che Redlock richiede ai client di garantire la coerenza delle scritture, e i nodi backend 5 sono completamente indipendenti, e tutti i client devono gestire questi 5 nodi. Se c'è un leader tra 5 nodi, il client può sincronizzare i dati del leader purché il client ottenga il lock dal leader, così che non ci saranno problemi come partizionamento, timeout e conflitti. Pertanto, per garantire la correttezza delle serrature distribuite, penso che l'uso di un servizio di coordinamento distribuito con forte coerenza possa risolvere meglio il problema.

La domanda si ripone: quanto tempo dovrei impostare il tempo di scadenza? Come impostare il tempo di invalidazione è troppo breve e il blocco viene rilasciato automaticamente prima che il metodo venga eseguito, quindi ci saranno problemi di concorrenza. Se ci vuole troppo, altri thread che si bloccano potrebbero dover aspettare molto.

Questo problema esiste anche con l'uso di database per implementare blocchi distribuiti.

L'approccio attuale a questo problema è impostare un breve timeout per ogni lock ottenuto e avviare un thread per aggiornare il timeout ogni volta che sta per raggiungerlo. Chiudi questa discussione contemporaneamente al rilascio della serratura. Ad esempio, redisson, il componente ufficiale distribuito di lock di redis, utilizza questa soluzione.

Vantaggi dell'uso della cache per implementare i blocchi distribuiti
Buona prestazione.

Svantaggi nell'usare la cache per implementare i blocchi distribuiti
L'implementazione è troppo responsabile, ci sono troppi fattori da considerare.

Blocchi distribuiti basati sull'implementazione di Zookeeper

Blocchi distribuiti basati su nodi temporanei ordinati di Zookeeper.

L'idea generale è che quando ogni client blocca un metodo, venga generato un unico nodo ordinato istantaneo nella directory del nodo specificato corrispondente al metodo su Zookeeper. Il modo per determinare se ottenere un blocco è semplice: basta determinare quello con il numero di serie più basso nel nodo ordinato. Quando il blocco viene rilasciato, basta eliminare il nodo istantaneo. Allo stesso tempo, può evitare il problema di blocchi causati da interruzioni del servizio che non possono essere liberati.

Vediamo se Zookeeper riesce a risolvere i problemi menzionati prima.

  • La serratura non si sblocca? L'uso di Zookeeper può risolvere efficacemente il problema dei locks che non vengono rilasciati, perché quando si crea un lock, il client crea un nodo temporaneo in ZK, e una volta che il client ottiene il lock e improvvisamente lo blocca (la connessione della sessione è interrotta), il nodo temporaneo verrà automaticamente eliminato. Altri clienti possono riprendere la serratura.
  • Serrature non bloccanti? Una volta che il nodo cambia, Zookeeper notificherà al client e il client potrà verificare se il nodo creato è il numero ordinale più piccolo tra tutti i nodi.
  • Non puoi rientrare? Quando il client crea un nodo, scrive direttamente le informazioni dell'host e del thread del client corrente al nodo, e la prossima volta che vuoi ottenere il blocco, puoi confrontarlo con i dati del nodo più piccolo attuale. Se le informazioni sono le stesse delle tue, puoi ottenere direttamente il blocco e, se è diverso, creare un nodo sequenziale temporaneo per partecipare alla coda.


La domanda si ripone: sappiamo che Zookeeper deve essere distribuito in cluster, ci saranno problemi di sincronizzazione dei dati come i cluster Redis?

Zookeeper è un componente distribuito che garantisce una coerenza debole, cioè una coerenza finale.

Zookeeper utilizza un protocollo di sincronizzazione dei dati chiamato Quorum Based Protocol. Se ci sono N server Zookeeper nel cluster Zookeeper (N è solitamente dispari, 3 possono garantire affidabilità dei dati e alte prestazioni di lettura e scrittura, e 5 hanno il miglior equilibrio tra affidabilità dei dati e prestazioni di lettura e scrittura), allora un'operazione di scrittura dell'utente viene prima sincronizzata con N/2 + 1 server, e poi restituita all'utente, invitando l'utente a scrivere con successo. Il protocollo di sincronizzazione dei dati basato sul Quorum Based Protocol determina la coerenza della potenza che Zookeeper può supportare.

In un ambiente distribuito, lo storage dati che mantiene una forte coerenza è praticamente inesistente e richiede che tutti i nodi vengano aggiornati in modo sincrono quando vengono aggiornati i dati di un solo nodo. Questa strategia di sincronizzazione appare nel database di replicazione sincrona master-slave. Tuttavia, questa strategia di sincronizzazione ha un impatto eccessivo sulle prestazioni di scrittura ed è raramente vista nella pratica. Poiché Zookeeper scrive N/2+1 nodi in modo sincrono e N/2 nodi non vengono aggiornati in modo sincrono, Zookeeper non è fortemente coerente.

L'operazione di aggiornamento dei dati dell'utente non garantisce che le letture successive leggano il valore aggiornato, ma alla fine mostrerà coerenza. Sacrificare la coerenza non significa ignorare completamente la coerenza dei dati, altrimenti i dati diventano caotici, quindi non importa quanto sia alta la disponibilità del sistema, non importa quanto sia buona la distribuzione, non ha alcun valore. Sacrificare la coerenza significa semplicemente che una forte coerenza nei database relazionali non è più necessaria, ma finché il sistema riesce a raggiungere la coerenza finale.

Una domanda su un solo punto? L'uso di Zookeeper può risolvere efficacemente un problema a un singolo punto, ZK viene distribuito in cluster; finché sopravvive più della metà delle macchine del cluster, il servizio può essere fornito al mondo esterno.

Problemi di equità? L'uso di Zookeeper può risolvere il problema dei locks equi, i nodi temporanei creati dal client in ZK sono ordinati e ogni volta che il lock viene rilasciato, ZK può notificare al nodo più piccolo di ottenere il lock, garantendo l'equità.

La domanda si ripone: sappiamo che Zookeeper deve essere distribuito in cluster, ci saranno problemi di sincronizzazione dei dati come i cluster Redis?

Zookeeper è un componente distribuito che garantisce una coerenza debole, cioè una coerenza finale.

Zookeeper utilizza un protocollo di sincronizzazione dei dati chiamato Quorum Based Protocol. Se ci sono N server Zookeeper nel cluster Zookeeper (N è solitamente dispari, 3 possono garantire affidabilità dei dati e alte prestazioni di lettura e scrittura, e 5 hanno il miglior equilibrio tra affidabilità dei dati e prestazioni di lettura e scrittura), allora un'operazione di scrittura dell'utente viene prima sincronizzata con N/2 + 1 server, e poi restituita all'utente, invitando l'utente a scrivere con successo. Il protocollo di sincronizzazione dei dati basato sul Quorum Based Protocol determina la coerenza della potenza che Zookeeper può supportare.

In un ambiente distribuito, lo storage dati che mantiene una forte coerenza è praticamente inesistente e richiede che tutti i nodi vengano aggiornati in modo sincrono quando vengono aggiornati i dati di un solo nodo. Questa strategia di sincronizzazione appare nel database di replicazione sincrona master-slave. Tuttavia, questa strategia di sincronizzazione ha un impatto eccessivo sulle prestazioni di scrittura ed è raramente vista nella pratica. Poiché Zookeeper scrive N/2+1 nodi in modo sincrono e N/2 nodi non vengono aggiornati in modo sincrono, Zookeeper non è fortemente coerente.

L'operazione di aggiornamento dei dati dell'utente non garantisce che le letture successive leggano il valore aggiornato, ma alla fine mostrerà coerenza. Sacrificare la coerenza non significa ignorare completamente la coerenza dei dati, altrimenti i dati diventano caotici, quindi non importa quanto sia alta la disponibilità del sistema, non importa quanto sia buona la distribuzione, non ha alcun valore. Sacrificare la coerenza significa semplicemente che una forte coerenza nei database relazionali non è più necessaria, ma finché il sistema riesce a raggiungere la coerenza finale.

Se Zookeeper soddisfi la coerenza causale dipende da come il cliente è programmato.

Pratiche che non soddisfano la coerenza causale

  • Il processo A scrive un dato nel /z di Zookeeper e lo restituisce con successo
  • Il processo A informa il processo B che A ha modificato i dati di /z
  • B legge i dati del /z di Zookeeper
  • Poiché il server dello Zookeeper collegato a B potrebbe non essere stato aggiornato con i dati scritti da A, B non potrà leggere i dati scritti da A


Pratiche che rispettano la coerenza causale

  • Il Processo B ascolta i cambiamenti di dati in /z su Zookeeper
  • Il processo A scrive un dato su /z di Zookeeper e, prima che venga restituito con successo, Zookeeper deve chiamare l'ascoltatore registrato su /z, e il leader notificherà B del cambiamento dei dati
  • Dopo che il metodo di risposta all'evento del processo B è stato risposto, prende i dati cambiati, quindi B potrà sicuramente ottenere il valore modificato
  • La coerenza causale qui si riferisce alla consistenza causale tra il Leader e B, cioè il Leader notifica i dati di un cambiamento


Il secondo meccanismo di ascolto degli eventi è anche il metodo che dovrebbe essere utilizzato per programmare correttamente Zookeeper, quindi Zookeeper dovrebbe rispettare la coerenza causale

Pertanto, quando implementiamo i lock distribuiti basati su Zookeeper, dovremmo utilizzare la pratica di soddisfare la coerenza causale, cioè i thread in attesa del lock ascoltano i cambiamenti nel lock di Zookeeper e, quando il lock viene rilasciato, Zookeeper notificherà al thread in attesa che soddisfa le condizioni di blocco equo.

Puoi usare direttamente il client di librerie di terze parti Zookeeper, che racchiude un servizio di blocco rientrante.

I lock distribuiti implementati con ZK sembrano corrispondere esattamente a ciò che ci aspettavamo da un lock distribuito all'inizio di questo articolo. Tuttavia, non lo è, e il blocco distribuito implementato da Zookeeper ha in realtà uno svantaggio, cioè le prestazioni potrebbero non essere alte come quelle del servizio di cache. Perché ogni volta che nel processo di creazione e rilascio di un lock, i nodi istantanei devono essere creati e distrutti dinamicamente per realizzare la funzione lock. La creazione e la cancellazione dei nodi in ZK può essere effettuata solo tramite il server leader, e poi i dati vengono condivisi con tutte le macchine follower.

Vantaggi dell'utilizzo di Zookeeper per implementare serrature distribuite
Risolvere efficacemente problemi di singolo punto, problemi di non rientro, problemi di non blocco e fallimento del blocco nel riaprire. È relativamente semplice da implementare.

Svantaggi nell'usare Zookeeper per implementare serrature distribuite
Le prestazioni non sono buone come l'uso della cache per implementare i lock distribuiti. È necessaria una comprensione dei principi di ZK.

Confronto tra le tre opzioni

Dal punto di vista della facilità di comprensione (dal basso all'alto)
Database > Cache > Zookeeper

Dal punto di vista della complessità dell'implementazione (da basso a alto)
Database > cache > Zookeeper

Dal punto di vista delle prestazioni (da alto a basso)
Cache > Zookeeper >= database

Dal punto di vista dell'affidabilità (da alto a basso)
Database > cache > Zookeeper





Precedente:Differenza tra annotazioni @Bean e @Service
Prossimo:Video tutorial per imparare il linguaggio C da zero
 Padrone di casa| Pubblicato su 22/09/2020 17:34:33 |
[Combattimento vero e proprio]. NET Core implementa lock distribuiti basati su Redis
https://www.itsvse.com/thread-9391-1-1.html

Implementazione di blocco distribuito .net/c# Zookeeper [codice sorgente]
https://www.itsvse.com/thread-4651-1-1.html

Disconoscimento:
Tutto il software, i materiali di programmazione o gli articoli pubblicati dalla Code Farmer Network sono destinati esclusivamente all'apprendimento e alla ricerca; I contenuti sopra elencati non devono essere utilizzati per scopi commerciali o illegali, altrimenti gli utenti dovranno sostenere tutte le conseguenze. Le informazioni su questo sito provengono da Internet, e le controversie sul copyright non hanno nulla a che fare con questo sito. Devi eliminare completamente i contenuti sopra elencati dal tuo computer entro 24 ore dal download. Se ti piace il programma, ti preghiamo di supportare software autentico, acquistare la registrazione e ottenere servizi autentici migliori. In caso di violazione, vi preghiamo di contattarci via email.

Mail To:help@itsvse.com