Informazioni sul passaggio da Redis al cluster Redis

Informazioni sul passaggio da Redis al cluster Redis

Venendo a un prodotto in sviluppo da più di un decennio, non sorprende affatto trovare al suo interno tecnologie obsolete. Ma cosa succede se in sei mesi devi mantenere il carico 10 volte più alto e il costo delle cadute aumenta centinaia di volte? In questo caso, hai bisogno di un bravo Highload Engineer. Ma in assenza di una cameriera, mi hanno affidato la risoluzione del problema. Nella prima parte dell'articolo ti racconterò come siamo passati da Redis a Redis-cluster, e nella seconda parte darò consigli su come iniziare a utilizzare il cluster e a cosa prestare attenzione quando lo si utilizza.

Selezione della tecnologia

È così brutto? Redis separati (Redis autonomo) in una configurazione di 1 master e N slave? Perché la chiamo tecnologia obsoleta?

No, Redis non è poi così male... Tuttavia, ci sono alcuni difetti che non possono essere ignorati.

  • Innanzitutto, Redis non supporta i meccanismi di ripristino di emergenza dopo un errore del master. Per risolvere questo problema, abbiamo utilizzato una configurazione con trasferimento automatico dei VIP a un nuovo master, cambiando il ruolo di uno degli slave e scambiando gli altri. Questo meccanismo ha funzionato, ma non può essere definito una soluzione affidabile. In primo luogo, si sono verificati falsi allarmi e, in secondo luogo, era usa e getta e dopo l'operazione erano necessarie azioni manuali per caricare la molla.

  • In secondo luogo, avere un solo master ha portato al problema dello sharding. Abbiamo dovuto creare diversi cluster indipendenti “1 master e N slave”, quindi distribuire manualmente i database tra queste macchine e sperare che domani uno dei database non si gonfiasse così tanto da dover essere spostato in un'istanza separata.

Quali sono le opzioni?

  • La soluzione più costosa e ricca è Redis-Enterprise. Si tratta di una soluzione in scatola con supporto tecnico completo. Nonostante sembri ideale dal punto di vista tecnico, non ci andava bene per ragioni ideologiche.
  • Cluster Redis. È immediatamente disponibile il supporto per il failover master e lo sharding. L'interfaccia non è quasi diversa dalla versione normale. Sembra promettente, delle insidie ​​​​parleremo più tardi.
  • Tarantool, Memcache, Aerospike e altri. Tutti questi strumenti fanno più o meno la stessa cosa. Ma ognuno ha i suoi difetti. Abbiamo deciso di non mettere tutte le uova nello stesso paniere. Usiamo Memcache e Tarantool per altri compiti e, guardando al futuro, dirò che nella nostra pratica c'erano più problemi con loro.

Specifiche d'uso

Diamo un'occhiata a quali problemi abbiamo storicamente risolto con Redis e quali funzionalità abbiamo utilizzato:

  • Cache prima delle richieste a servizi remoti come 2GIS | Golang

    GET SET MGET MSET "SELEZIONA DB"

  • Cache prima di MYSQL | PHP

    GET SET MGET MSET SCAN "KEY BY PATTERN" "SELECT DB"

  • Lo spazio di archiviazione principale per il servizio di lavoro con sessioni e coordinate del conducente | Golang

    OTTIENI IMPOSTA MGET MSET "SELEZIONA DB" "AGGIUNGI CHIAVE GEO" "OTTIENI CHIAVE GEO" SCANSIONE

Come puoi vedere, nessuna matematica superiore. Qual è allora la difficoltà? Diamo un'occhiata a ciascun metodo separatamente.

metodo
descrizione
Funzionalità del cluster Redis
Soluzione

PREPARATEVI
Chiave di scrittura/lettura

MGET MSET
Scrivere/leggere più chiavi
Le chiavi saranno su nodi diversi. Le librerie già pronte possono eseguire operazioni multiple solo all'interno di un nodo
Sostituisci MGET con una pipeline di operazioni N GET

SELEZIONA DB
Seleziona la base con cui lavoreremo
Non supporta più database
Metti tutto in un unico database. Aggiungi prefissi alle chiavi

SCAN
Passa attraverso tutte le chiavi nel database
Poiché abbiamo un database, esaminare tutte le chiavi nel cluster è troppo costoso
Mantieni un invariante all'interno di una chiave ed esegui un HSCAN su questa chiave. Oppure rifiuta completamente

GEO
Operazioni con una geochiave
La chiave geografica non viene partizionata

CHIAVE PER MODELLO
Ricerca di una chiave per pattern
Poiché abbiamo un database, effettueremo la ricerca in tutte le chiavi nel cluster. Troppo caro
Rifiutare o mantenere l'invariante, come nel caso di SCAN

Redis vs cluster Redis

Cosa perdiamo e cosa guadagniamo passando a un cluster?

  • Svantaggi: perdiamo la funzionalità di diversi database.
    • Se vogliamo archiviare dati logicamente non correlati in un cluster, dovremo creare stampelle sotto forma di prefissi.
    • Perdiamo tutte le operazioni “base”, come SCAN, DBSIZE, CLEAR DB, ecc.
    • Le operazioni multiple sono diventate molto più difficili da implementare perché potrebbero richiedere l'accesso a diversi nodi.
  • vantaggi:
    • Tolleranza agli errori sotto forma di failover principale.
    • Sharding sul lato Redis.
    • Trasferisci i dati tra i nodi in modo atomico e senza tempi di inattività.
    • Aggiungi e ridistribuisci capacità e carichi senza tempi di inattività.

Vorrei concludere che se non è necessario fornire un livello elevato di tolleranza agli errori, non vale la pena passare a un cluster, perché può essere un compito non banale. Ma se inizialmente scegli tra una versione separata e una versione cluster, allora dovresti scegliere un cluster, poiché non è peggiore e, inoltre, ti solleverà da alcuni mal di testa

Preparazione al trasloco

Partiamo dai requisiti per il trasloco:

  • Dovrebbe essere senza soluzione di continuità. Una sospensione completa del servizio per 5 minuti non è adatta a noi.
  • Dovrebbe essere il più sicuro e graduale possibile. Voglio avere un certo controllo sulla situazione. Non vogliamo scaricare tutto in una volta e pregare sul pulsante di rollback.
  • Perdita di dati minima durante lo spostamento. Comprendiamo che sarà molto difficile spostarsi in modo atomico, quindi consentiamo una certa desincronizzazione tra i dati in Redis normali e in cluster.

Manutenzione del cluster

Poco prima del trasloco, dovremmo pensare se possiamo sostenere il cluster:

  • Grafici. Utilizziamo Prometheus e Grafana per rappresentare graficamente il carico della CPU, l'utilizzo della memoria, il numero di client, il numero di operazioni GET, SET, AUTH, ecc.
  • Competenza. Immagina che domani avrai un enorme cluster sotto la tua responsabilità. Se si rompe, nessuno tranne te può ripararlo. Se inizia a rallentare, tutti correranno verso di te. Se hai bisogno di aggiungere risorse o ridistribuire il carico, torna da te. Per non diventare grigi a 25 anni è opportuno prevedere questi casi e verificare in anticipo come si comporterà la tecnologia in determinate azioni. Ne parliamo più in dettaglio nella sezione “Competenza”.
  • Monitoraggio e avvisi. Quando un cluster si guasta, vuoi essere il primo a saperlo. Qui ci siamo limitati a notificare che tutti i nodi restituiscono le stesse informazioni sullo stato del cluster (sì, succede diversamente). E altri problemi possono essere notati più rapidamente dagli avvisi dei servizi client Redis.

Spostare

Come ci sposteremo:

  • Prima di tutto, devi preparare una libreria per lavorare con il cluster. Abbiamo preso go-redis come base per la versione Go e l'abbiamo leggermente modificato per adattarlo alle nostre esigenze. Abbiamo implementato metodi multipli tramite pipeline e abbiamo anche leggermente corretto le regole per la ripetizione delle richieste. La versione PHP presentava più problemi, ma alla fine abbiamo optato per php-redis. Recentemente hanno introdotto il supporto dei cluster e secondo noi sembra buono.
  • Successivamente è necessario distribuire il cluster stesso. Questo viene fatto letteralmente in due comandi basati sul file di configurazione. Discuteremo l'impostazione in modo più dettagliato di seguito.
  • Per lo spostamento graduale utilizziamo la modalità a secco. Dato che abbiamo due versioni della libreria con la stessa interfaccia (una per la versione normale, l'altra per il cluster), non costa nulla creare un wrapper che funzionerà con una versione separata e duplicherà in parallelo tutte le richieste al cluster, confrontare le risposte e scrivere le discrepanze nei log (nel nostro caso in NewRelic). Pertanto, anche se la versione del cluster si rompesse durante il rollout, la nostra produzione non ne risentirebbe.
  • Dopo aver implementato il cluster in modalità dry, possiamo guardare con calma il grafico delle discrepanze nelle risposte. Se il tasso di errore si sposta lentamente ma inesorabilmente verso una piccola costante, allora va tutto bene. Perché ci sono ancora discrepanze? Poiché la registrazione in una versione separata avviene un po' prima rispetto al cluster e, a causa del microlag, i dati potrebbero divergere. Tutto ciò che resta da fare è guardare i registri delle discrepanze e, se sono tutti spiegati dalla non atomicità del record, allora possiamo andare avanti.
  • Ora puoi cambiare la modalità dry nella direzione opposta. Scriveremo e leggeremo dal cluster e lo duplicheremo in una versione separata. Per quello? Nella prossima settimana vorrei osservare il lavoro del cluster. Se all'improvviso si scopre che ci sono problemi durante i picchi di carico o non abbiamo tenuto conto di qualcosa, grazie alla modalità dry abbiamo sempre un ripristino di emergenza al vecchio codice e ai dati attuali.
  • Non resta che disabilitare la modalità dry e smantellare la versione separata.

esame

Innanzitutto, brevemente sulla progettazione del cluster.

Prima di tutto, Redis è un negozio di valori-chiave. Come chiavi vengono utilizzate stringhe arbitrarie. Numeri, stringhe e intere strutture possono essere utilizzate come valori. Questi ultimi sono moltissimi, ma per comprendere la struttura generale questo non è importante per noi.
Il livello di astrazione successivo dopo le chiavi sono gli slot (SLOTS). Ogni chiave appartiene a uno dei 16 slot. Può esserci un numero qualsiasi di chiavi all'interno di ogni slot. Pertanto, tutte le chiavi sono divise in 383 insiemi disgiunti.
Informazioni sul passaggio da Redis al cluster Redis

Successivamente, devono esserci N nodi master nel cluster. Ogni nodo può essere considerato come un'istanza Redis separata che sa tutto sugli altri nodi all'interno del cluster. Ogni nodo principale contiene un numero di slot. Ogni slot appartiene ad un solo nodo master. Tutti gli slot devono essere distribuiti tra i nodi. Se alcuni slot non vengono assegnati, le chiavi in ​​essi memorizzate saranno inaccessibili. Ha senso eseguire ciascun nodo master su una macchina logica o fisica separata. Vale anche la pena ricordare che ogni nodo funziona solo su un core e, se desideri eseguire più istanze Redis sulla stessa macchina logica, assicurati che vengano eseguite su core diversi (non l'abbiamo provato, ma in teoria dovrebbe funzionare) . In sostanza, i nodi master forniscono sharding regolare e più nodi master consentono la scalabilità delle richieste di scrittura e lettura.

Dopo che tutte le chiavi sono state distribuite tra gli slot e gli slot sono stati sparsi tra i nodi master, è possibile aggiungere un numero arbitrario di nodi slave a ciascun nodo master. All'interno di ciascun collegamento master-slave funzionerà la replica normale. Gli slave sono necessari per ridimensionare le richieste di lettura e per il failover in caso di guasto del master.
Informazioni sul passaggio da Redis al cluster Redis

Ora parliamo delle operazioni che sarebbe meglio poter fare.

Accederemo al sistema tramite Redis-CLI. Poiché Redis non dispone di un singolo punto di ingresso, puoi eseguire le seguenti operazioni su qualsiasi nodo. In ogni punto attiro separatamente l'attenzione sulla possibilità di eseguire l'operazione sotto carico.

  • La prima e più importante cosa di cui abbiamo bisogno è il funzionamento dei nodi del cluster. Restituisce lo stato del cluster, mostra un elenco di nodi, i loro ruoli, la distribuzione degli slot, ecc. È possibile ottenere ulteriori informazioni utilizzando le informazioni sul cluster e gli slot del cluster.
  • Sarebbe bello poter aggiungere e rimuovere nodi. A questo scopo esistono operazioni di cluster meet e cluster dimenticato. Tieni presente che l'oblio del cluster deve essere applicato a OGNI nodo, sia master che repliche. E il cluster meet deve essere chiamato solo su un nodo. Questa differenza può essere sconcertante, quindi è meglio conoscerla prima di attivare il cluster. L'aggiunta di un nodo viene eseguita in modo sicuro in battaglia e non influisce in alcun modo sul funzionamento del cluster (il che è logico). Se intendi rimuovere un nodo dal cluster, assicurati che non siano rimasti slot su di esso (altrimenti rischi di perdere l'accesso a tutte le chiavi su questo nodo). Inoltre, non eliminare un master che ha degli slave, altrimenti verrà eseguita una votazione non necessaria per un nuovo master. Se i nodi non hanno più slot, allora questo è un piccolo problema, ma perché abbiamo bisogno di scelte extra se possiamo prima eliminare gli slave?
  • Se è necessario scambiare forzatamente le posizioni master e slave, sarà sufficiente il comando di failover del cluster. Quando lo chiami in battaglia, devi capire che il maestro non sarà disponibile durante l'operazione. In genere il passaggio avviene in meno di un secondo, ma non è atomico. Puoi aspettarti che alcune richieste al master falliscano durante questo periodo.
  • Prima di rimuovere un nodo dal cluster, su di esso non dovrebbero essere rimasti slot. È meglio ridistribuirli utilizzando il comando cluster reshard. Gli slot verranno trasferiti da un master all'altro. L'intera operazione può richiedere diversi minuti, dipende dal volume di dati trasferiti, ma il processo di trasferimento è sicuro e non pregiudica in alcun modo il funzionamento del cluster. Pertanto, tutti i dati possono essere trasferiti da un nodo all'altro direttamente sotto carico e senza preoccuparsi della loro disponibilità. Tuttavia, ci sono anche delle sottigliezze. Innanzitutto, il trasferimento dei dati è associato a un determinato carico sui nodi destinatario e mittente. Se il nodo destinatario è già pesantemente caricato sul processore, non dovresti caricarlo con la ricezione di nuovi dati. In secondo luogo, non appena non rimane più uno slot sul master mittente, tutti i suoi slave andranno immediatamente al master a cui sono stati trasferiti questi slot. E il problema è che tutti questi schiavi vorranno sincronizzare i dati contemporaneamente. E sarai fortunato se la sincronizzazione sarà parziale anziché completa. Tenerne conto e combinare le operazioni di trasferimento degli slot e di disabilitazione/trasferimento degli slave. Oppure spero di avere un margine di sicurezza sufficiente.
  • Cosa dovresti fare se, durante il trasferimento, scopri di aver perso i tuoi slot da qualche parte? Spero che questo problema non ti riguardi, ma se lo fa, è disponibile un'operazione di correzione del cluster. Per lo meno, spargerà gli slot sui nodi in ordine casuale. Consiglio di verificarne il funzionamento rimuovendo prima dal cluster il nodo con gli slot distribuiti. Poiché i dati negli slot non assegnati non sono già disponibili, è troppo tardi per preoccuparsi di problemi con la disponibilità di questi slot. A sua volta l'operazione non influirà sugli slot distribuiti.
  • Un'altra operazione utile è monitorare. Ti permette di vedere in tempo reale l'intero elenco delle richieste che arrivano al nodo. Inoltre, puoi grepparlo e scoprire se c'è il traffico necessario.

Vale anche la pena menzionare la procedura di failover principale. Insomma, esiste e, secondo me, funziona benissimo. Tuttavia, non pensare che se scolleghi il cavo di alimentazione su una macchina con un nodo master, Redis passerà immediatamente e i client non noteranno la perdita. Nella mia pratica, il passaggio avviene in pochi secondi. Durante questo periodo, alcuni dati non saranno disponibili: viene rilevata l’indisponibilità del master, i nodi votano per uno nuovo, gli slave vengono scambiati, i dati vengono sincronizzati. Il modo migliore per assicurarsi personalmente che il programma funzioni è condurre esercitazioni locali. Alza il cluster sul tuo laptop, assegnagli un carico minimo, simula un arresto anomalo (ad esempio bloccando le porte) e valuta la velocità di commutazione. Secondo me, solo dopo aver giocato in questo modo per un giorno o due puoi essere sicuro del funzionamento della tecnologia. Bene, o spero che il software utilizzato da metà di Internet probabilmente funzioni.

Configurazione

Spesso la configurazione è la prima cosa di cui hai bisogno per iniziare a lavorare con lo strumento e quando tutto funziona, non vuoi nemmeno toccare la configurazione. Ci vuole un certo sforzo per costringerti a tornare alle impostazioni e esaminarle attentamente. Che io ricordi, abbiamo avuto almeno due guasti gravi dovuti a disattenzione nella configurazione. Prestare particolare attenzione ai seguenti punti:

  • timeout 0
    Tempo dopo il quale le connessioni inattive vengono chiuse (in secondi). 0 - non chiudere
    Non tutte le nostre biblioteche sono state in grado di chiudere correttamente le connessioni. Disabilitando questa impostazione, rischiamo di raggiungere il limite del numero di client. D'altra parte, se si verifica un problema del genere, la terminazione automatica delle connessioni perse lo maschererà e potremmo non notarlo. Inoltre, non dovresti abilitare questa impostazione quando utilizzi connessioni persistenti.
  • Salva xy e aggiungi solo sì
    Salvataggio di uno snapshot RDB.
    Discuteremo in dettaglio le questioni RDB/AOF di seguito.
  • stop-writes-on-bgsave-error no e slave-serve-stale-data sì
    Se abilitato, se lo snapshot RDB si interrompe, il master smetterà di accettare richieste di modifica. Se si perde la connessione con il master, lo slave può continuare a rispondere alle richieste (sì). Oppure smetterà di rispondere (no)
    Non siamo contenti della situazione in cui Redis si trasforma in una zucca.
  • periodo-repl-ping-slave 5
    Trascorso questo periodo di tempo inizieremo a preoccuparci che il master sia guasto ed è giunto il momento di effettuare la procedura di failover.
    Sarà necessario trovare manualmente un equilibrio tra i falsi positivi e l'attivazione di un failover. Nella nostra pratica questo è di 5 secondi.
  • repl-backlog-size 1024mb & epl-backlog-ttl 0
    Possiamo archiviare esattamente questa quantità di dati in un buffer per una replica fallita. Se il buffer si esaurisce, dovrai sincronizzarti completamente.
    La pratica suggerisce che è meglio impostare un valore più alto. Ci sono molte ragioni per cui una replica potrebbe iniziare a rallentare. Se ritarda, molto probabilmente il tuo master sta già lottando per farcela e la sincronizzazione completa sarà l'ultima goccia.
  • clienti massimi 10000
    Numero massimo di client occasionali.
    Secondo la nostra esperienza è meglio impostare un valore più alto. Redis gestisce perfettamente le connessioni da 10k. Assicurati solo che ci siano abbastanza prese nel sistema.
  • maxmemory-policy volatile-ttl
    La regola in base alla quale le chiavi vengono eliminate quando viene raggiunto il limite di memoria disponibile.
    Ciò che è importante qui non è la regola in sé, ma la comprensione di come ciò avverrà. Redis può essere elogiato per la sua capacità di funzionare normalmente quando viene raggiunto il limite di memoria.

Problemi RDB e AOF

Sebbene Redis stesso memorizzi tutte le informazioni nella RAM, esiste anche un meccanismo per salvare i dati su disco. Più precisamente, tre meccanismi:

  • Istantanea RDB: un'istantanea completa di tutti i dati. Impostato utilizzando la configurazione SAVE XY e legge "Salva un'istantanea completa di tutti i dati ogni X secondi se almeno i tasti Y sono cambiati".
  • File di sola aggiunta: un elenco di operazioni nell'ordine in cui vengono eseguite. Aggiunge nuove operazioni in entrata al file ogni X secondi o ogni Y operazioni.
  • RDB e AOF sono una combinazione dei due precedenti.

Tutti i metodi hanno i loro vantaggi e svantaggi, non li elencherò tutti, mi limiterò a richiamare l'attenzione su punti che, secondo me, non sono evidenti.

Innanzitutto, il salvataggio di uno snapshot RDB richiede la chiamata a FORK. Se sono presenti molti dati, ciò può bloccare tutto Redis per un periodo compreso tra pochi millisecondi e un secondo. Inoltre, il sistema deve allocare memoria per tale snapshot, il che porta alla necessità di mantenere una doppia fornitura di RAM sulla macchina logica: se vengono allocati 8 GB per Redis, allora sulla macchina virtuale dovrebbero essere disponibili 16 GB con Esso.

In secondo luogo, ci sono problemi con la sincronizzazione parziale. Nella modalità AOF, quando lo slave viene ricollegato, invece della sincronizzazione parziale, è possibile eseguire la sincronizzazione completa. Perché questo accada, non riuscivo a capire. Ma vale la pena ricordarlo.

Questi due punti ci fanno già pensare se abbiamo davvero bisogno di questi dati sul disco se tutto è già duplicato dagli schiavi. I dati possono andare persi solo se tutti gli slave falliscono, e questo è un problema di livello “incendio nel DC”. Come compromesso, puoi proporre di salvare i dati solo sugli slave, ma in questo caso devi assicurarti che questi slave non diventino mai master durante il ripristino di emergenza (per questo esiste un'impostazione di priorità dello slave nella loro configurazione). Per quanto ci riguarda, in ogni caso specifico pensiamo se sia necessario salvare i dati su disco e molto spesso la risposta è "no".

conclusione

In conclusione, spero di essere riuscito a dare un'idea generale di come funziona redis-cluster per coloro che non ne hanno mai sentito parlare, e anche di attirare l'attenzione su alcuni punti non ovvi per coloro che lo utilizzano per molto tempo.
Grazie per il tuo tempo e, come sempre, i commenti sull'argomento sono benvenuti.

Fonte: habr.com

Aggiungi un commento