Non ci sono recensioni su «un'alternativa più veloce a Redis» su Habr — . Avere accumulato un'esperienza abbastanza recente del suo utilizzo, desidero colmare questa lacuna.
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/9642ef3dc712ad2e6304104facb464b7.jpeg)
La storia è piuttosto banale: un giorno, con un grande afflusso di traffico, è stata registrata una significativa degradazione delle prestazioni dell'applicazione (in particolare, dei tempi di risposta). In quel momento, sfortunatamente, non siamo riusciti a condurre una diagnosi adeguata della situazione, quindi in seguito abbiamo pianificato una serie di test di carico. Dopo averli eseguiti, siamo stati in grado di identificare un collo di bottiglia, rappresentato dalla cache del database in Redis. Come spesso accade, non si poteva risolvere il problema immediatamente e nel modo corretto — con l'intervento degli sviluppatori (cambiando la logica di funzionamento). Pertanto, si è accesa la curiosità e il desiderio di affrontare la situazione in modo alternativo. È così che è nato questo articolo.
Problematica
Su Redis in generale
Come molti sanno, Redis è un database a thread singolo. Per essere più precisi, lo è nel contesto della gestione dei dati degli utenti. Da quando è stata introdotta la quarta versione, le operazioni interne e di servizio in Redis sono eseguite in parallelo. Tuttavia, questa modifica ha riguardato solo una piccola parte del carico, poiché il lavoro principale è concentrato sui dati degli utenti.
Su questo tema sono state scritte innumerevoli pagine, ma gli sviluppatori di Redis si rifiutano di implementare una vera parallelità, menzionando quanto ciò complicherebbe l'applicazione e aumenterebbe i costi generali, oltre a introdurre un numero maggiore di bug. La loro posizione è la seguente: se ti trovi di fronte a un problema di mono-core — hai problemi con l'architettura dell'applicazione e devi modificarla. Tuttavia, tra gli utenti c'è anche un "altro gruppo" — quelli che si sono bloccati su un singolo core e affermano che Redis crea bottlenecks autonomamente. In caso di carichi realmente elevati — prima o poi — ci si imbatte inevitabilmente in questo problema, il che impone significativi vincoli sull'architettura e/o indesiderate complicazioni.
Non darò un giudizio su una o l'altra opinione. Invece, condividerò il nostro caso specifico e come lo abbiamo risolto.
Il nostro caso
In uno dei progetti ci siamo trovati di fronte al fatto che il team di sviluppo aveva impostato una cache dei dati dal database (PostgreSQL) tramite Redis in modo estremamente aggressivo. Questa era l'unica soluzione che, durante i forti picchi di traffico, salvava PostgreSQL e, di conseguenza, l'applicazione dalla morte.
Dopo una serie di test di carico, abbiamo effettuato un'analisi della situazione e scoperto che Redis si bloccava su un solo core (quello che si chiama «in trincea»), dopodiché seguiva una degradazione abbastanza rapida dell'applicazione. Il «sovraccarico» aveva una progressione geometrica: non appena si raggiungeva il limite delle prestazioni di Redis, tutto smetteva di funzionare.
Si presentava più o meno così:
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/c0f55ca1d9f28f8c305bb74cdc77a84a.jpeg)
Dalla parte di New Relic è stata chiaramente identificata la problematica:
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/ce72e290f84560d143f2d6c128358477.jpeg)
Ed ecco le statistiche sull'operazione get in Redis:
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/31d98a6bb2985cfbe391976e24b8a8a6.jpeg)
Dopo aver comunicato il problema in tutti i dettagli agli sviluppatori, è emerso che "al momento non è possibile risolvere il problema". Così sono iniziate le ricerche di una soluzione dal lato dell'esercizio, e la risposta è stata l già menzionata KeyDB.
Tuttavia, prima di procedere con la sua revisione, vale la pena menzionare che nel progetto viene utilizzato Redis standalone, poiché una soluzione cluster basata su Sentinel ha latenze (latency) molto superiori. Una delle soluzioni ovvie era creare più repliche della cache: che l'applicazione si connettesse ovunque con bilanciamento! Tuttavia, dopo aver consultato gli sviluppatori, siamo stati costretti a scartare questa opzione a causa del meccanismo complesso e attivo di invalidazione della cache nell'applicazione. La stessa problematica si estendeva anche al partizionamento della cache.
Una rapida panoramica di KeyDB
In cerca di una possibile soluzione al problema, abbiamo scoperto . È un fork di Redis, sviluppato e distribuito con licenza open source BSD. Il progetto è piuttosto giovane: è stato avviato all'inizio del 2019. La sua storia è che anche gli autori si sono trovati un giorno di fronte alle limitazioni di Redis… e hanno deciso di fare il proprio fork. Inoltre, non solo ha risolto i problemi noti, ma ha anche ottenuto funzionalità aggiuntive disponibili solo nella versione enterprise di Redis.
Per coloro che desiderano approfondire KeyDB, è disponibile un'ottima , che presenta il DBMS e brevi benchmark che lo confrontano con il suo "genitore" — Redis.
Prima di tutto, ciò che ci ha attratto di KeyDB è stata la potenziale soluzione ai nostri problemi, insieme ad alcune funzionalità aggiuntive interessanti. L'uso di KeyDB prometteva i seguenti vantaggi:
- ottenere una vera multithreading;
- completa e assoluta compatibilità con Redis (per noi era particolarmente importante, poiché non era possibile apportare modifiche dal lato applicazione), il che presagiva anche una migrazione senza problemi;
- meccanismo di backup integrato nello storage S3;
- replicazione attiva semplice da implementare;
- clusterizzazione e sharding semplici senza Sentinel e altro software di supporto.
Oltre 3.000 stelle e numerosi collaboratori su GitHub hanno anche dato buone speranze. L'applicazione si sviluppa e viene supportata attivamente, come è evidente dai commit, dalla comunicazione nelle issues e dai PR chiusi (accettati). La risposta del mantenitore principale è sempre cordiale e tempestiva. In sintesi, ci sono state abbastanza argomentazioni.
Migrazione e risultati
Anche se il progetto di migrazione era una sorta di avventura (dati i tempi brevi di KeyDB), non c'era molto da perdere. Infatti, ripristinare le modifiche è stato abbastanza rapido e semplice: l'intera infrastruttura è implementata su Kubernetes, e i meccanismi integrati risolvono ottimamente tali compiti.
In generale, abbiamo preparato modelli Helm, abbiamo commutato l'applicazione nell'ambiente di test sul nuovo database e abbiamo lanciato tutto, passando al reparto QA del cliente.
È iniziato il collaudo, durato circa una settimana di cui non siamo andati nei dettagli. Sappiamo solo che il cliente ha testato le funzionalità standard di interazione con Redis tramite il driver PHP , e ha condotto anche test di QA sull'interfaccia utente. Dopo di che, ci hanno dato il via libera: non sono stati riscontrati effetti collaterali nell'uso del nuovo software. Cioè, dal punto di vista dell'applicazione non è cambiato nulla.
Vale la pena notare che anche nella configurazione non abbiamo apportato modifiche: praticamente, abbiamo semplicemente sostituito l'immagine utilizzata. Lo stesso vale per il monitoraggio e l'esportazione delle metriche in Prometheus: funziona perfettamente con KeyDB e senza alcuna modifica. Pertanto, si può tranquillamente affermare che anche dal punto di vista operativo questo è un trasferimento semplicemente ideale.
Grazie a tutto questo, dopo aver migrato l'applicazione al nuovo DBMS, non è necessario apportare modifiche, e come "misura di stabilizzazione" - lasciarlo così per funzionare in produzione per un certo periodo. Tuttavia, se desiderate vedere un aumento delle prestazioni (o comunque qualche cambiamento), non dimenticate che predefinito il parametro KeyDB, responsabile del multithreading (server-threads), è uguale a uno, ovvero il DBMS funziona esattamente come Redis.
Dopo la migrazione, i test e un certo periodo di vita sulla nuova applicazione (con KeyDB) abbiamo deciso di ripetere il test di carico con gli stessi parametri utilizzati per Redis. Quali sono stati i risultati?..
Dal grafico del consumo della CPU si nota subito l'eliminazione dei problemi con il "tetto" a un core: il processo ha iniziato a utilizzare le risorse disponibili:
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/8a3a168507ef75a8e1cdf69e1d30d996.jpeg)
E successivamente ho provato a "stressare" abbastanza l'applicazione e ho visto un consumo fino a tre core...
Secondo le indicazioni di New Relic, l'applicazione web, pur mantenendo lo stesso carico, ha iniziato a comportarsi in modo significativamente più appropriato. Si è comunque osservata una certa degradazione delle prestazioni, tuttavia, confrontando con il grafico simile sopra, potete valutare voi stessi i progressi sostanziali:
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/f46bf41bd6b8d190f5117d049ed2dce5.jpeg)
L'indicatore di latenza del nuovo database (KeyDB) è anch'esso peggiorato, ma è rimasto entro i limiti accettabili:
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/b9e0a3103a51707628a9f500dfdd53ad.jpeg)
Dal seguente grafico è evidente che il numero di richieste a KeyDB è simile:
![KeyDB come [potenziale] sostituto di Redis](/wp-content/uploads/2020/02/0a067239194adb39eb3c3738fa73860e.jpeg)
In sintesi, è possibile affermare che sia Redis che KeyDB mostrano una significativa degradazione delle prestazioni in termini di latenza (40 ms+) con un notevole aumento del numero di connessioni parallele (oltre 1000). Nel nostro caso, l'applicazione web riusciva a "ridurre" la latenza di Redis anche con un numero di connessioni inferiore (oltre 400), sebbene per KeyDB questo carico rimanesse accettabile.
Conclusioni
In questo esempio si può chiaramente vedere la forza della comunità Open Source nello sviluppo dei progetti di cui è interessata. Sul web ho trovato una frase interessante il cui significato generale è il seguente: «Qualche grande azienda crea un prodotto interessante, rende parte delle sue funzioni aperta, ma lascia a pagamento la parte più importante. La comunità lo utilizza, poi qualcuno alza le spalle e realizza un fork, implementando proprio quelle funzioni a pagamento e rendendole disponibili per tutti». Ecco, KeyDB è proprio questo caso.
Parlando della migrazione, che è avvenuta sorprendentemente senza problemi, non abbiamo ricevuto un incremento significativo in termini di performance, quello che ci si aspetterebbe osservando i grafici degli autori di KeyDB… Tuttavia, questo è solo il nostro caso specifico, in cui potrebbero esserci molte variazioni, riguardanti anche la tanto discussa architettura dell'applicazione (ad esempio, il grande numero di comandi get in Redis invece di una soluzione più performante come le richieste aggregate mget…). Tuttavia, siamo riusciti a ottenere risultati positivi, insieme a molte funzionalità utili che implementeremo nei prossimi tempi.
Complessivamente, KeyDB appare promettente: con l'aumentare dell'esperienza pratica nell'uso di questo DBMS (che dobbiamo ancora acquisire!) e lo sviluppo del progetto stesso, valuteremo la possibilità di applicarlo anche in altre situazioni.
Tuttavia, non bisogna considerare questo articolo come una guida (e tanto meno come un invito) ad abbandonare Redis in favore di KeyDB. Nonostante la nostra esperienza positiva, è evidente che non si tratta di una soluzione miracolosa. Il caso è stato piuttosto specifico: esattamente per risolvere un problema immediato in una situazione dove occorreva agire rapidamente e con costi minimi, tale soluzione si è rivelata efficace. Sarà KeyDB utile nel vostro caso? Almeno ora sapete che tale opportunità potenziale esiste.
P.S.
Leggi anche nel nostro blog:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
