KeyDB come [potenziale] sostituto di Redis

Su Habr non ci sono recensioni di 'alternative più rapide a Redis' — KeyDB. Avendo acquisito una certa esperienza recente nel suo utilizzo, vorrei colmare questa lacuna.

KeyDB come [potenziale] sostituto di Redis

La storia è abbastanza banale: una volta, con un grande afflusso di traffico, è stata registrata una significativa degradazione delle prestazioni dell'applicazione (in particolare, del tempo di risposta). In quel momento, sfortunatamente, non siamo riusciti a condurre una diagnosi adeguata di quanto accadeva, quindi successivamente abbiamo pianificato una serie di test di carico. Dopo averli eseguiti, siamo riusciti a scoprire il collo di bottiglia, rappresentato dalla cache del database in Redis. Come spesso accade, non è stato possibile risolvere il problema immediatamente e nel modo giusto — tramite gli sviluppatori (modificando la logica operativa). Così, la curiosità e il desiderio di affrontare la situazione in modo alternativo sono emersi. Ecco come è nato questo articolo.

Problematiche

Su Redis in generale

Come è noto a molti, Redis è un database a thread singolo. Se vogliamo essere più precisi, lo è nel contesto della gestione dei dati degli utenti. Infatti, dalla quarta versione, operazioni di servizio e interne di Redis sono state trasferite per l'esecuzione parallela. Tuttavia, questa modifica ha riguardato solo una piccola parte del carico, poiché il lavoro principale ricade sui dati degli utenti.

Sono state scritte innumerevoli copie sull'argomento, ma gli sviluppatori di Redis si rifiutano di implementare una vera e propria parallelizzazione, citando come questo complicherebbe l'applicazione e aumenterebbe i costi, oltre a creare più bug. La loro posizione è che se hai un problema di monocore, hai problemi con l'architettura dell'applicazione e devi apportare delle modifiche. Tuttavia, tra gli utenti c'è anche 'l'altro campo' — coloro che si sono arenati su un solo core e affermano che Redis stesso crea un collo di bottiglia. In caso di carichi davvero elevati, prima o poi, si incontrerà inevitabilmente questo problema, il che impone significative limitazioni all'architettura e/o forzate complicazioni in essa.

Non intendo esprimere un giudizio su opinioni particolari. Invece, condividerò il nostro caso specifico e come lo abbiamo risolto.

Il nostro caso

In one of our projects, we encountered a situation where the development team had set up extremely aggressive caching of data from the database (PostgreSQL) through Redis. This was the only way to save PostgreSQL itself during sharp traffic spikes, which, consequently, saved the application.

After a series of load tests, we analyzed the situation and discovered that Redis was maxing out on a single core (what's known as being 'bottlenecked'), after which there was a rapid degradation of the application. The 'choking' followed a geometric progression: as soon as Redis reached its performance limit, everything stopped working.

It looked something like this:

KeyDB come [potenziale] sostituto di Redis

From the perspective of New Relic, the problem was clearly identified:

KeyDB come [potenziale] sostituto di Redis

Here is the statistics for the operation get in Redis:

KeyDB come [potenziale] sostituto di Redis

After the problem was conveyed in detail to the development team, it became clear that 'the problem cannot be solved right now.' Thus, the search for a solution on the operational side began, and the response was the already mentioned KeyDB.

Tuttavia, prima di iniziare la sua recensione, è importante menzionare che nel progetto viene utilizzato Redis standalone, poiché la soluzione cluster basata su Sentinel presenta latenze significativamente maggiori. Una delle soluzioni ovvie era creare più repliche della cache: e lasciare che l'applicazione accedesse ovunque con bilanciamento! Tuttavia, dopo aver consultato gli sviluppatori, abbiamo dovuto scartare questa opzione a causa del meccanismo attivo e complesso di invalidazione della cache dell'applicazione. Lo stesso problema si applicava anche al partizionamento della cache.

Panoramica di KeyDB

Alla ricerca di una possibile soluzione al problema, abbiamo scoperto un'applicazione chiamata KeyDB. Si tratta di un fork di Redis, sviluppato da un'azienda canadese e distribuito con licenza libera BSD. Il progetto è piuttosto giovane: esiste sin dall'inizio del 2019. La sua storia è tale che anche gli autori una volta si sono scontrati con le limitazioni di Redis… e hanno deciso di creare il loro fork. Inoltre, non solo ha risolto i problemi noti, ma ha anche ottenuto funzionalità aggiuntive che sono disponibili solo nella versione enterprise di Redis.

Per coloro che desiderano approfondire KeyDB, c'è un ottimo articolo introduttivo su Medium, che presenta un database e brevi benchmark che lo confrontano con il suo "genitore" — Redis.

In primo luogo, ciò che ci ha attratti in KeyDB è stata la potenziale soluzione ai nostri problemi, oltre ad alcune funzionalità aggiuntive. L'uso di KeyDB prometteva i seguenti vantaggi:

  • ottenere una vera multithreading;
  • completa e assoluta compatibilità con Redis (per noi questo era particolarmente importante, poiché non era possibile apportare modifiche a livello applicativo), il che comportava anche una migrazione senza problemi;
  • meccanismo di backup integrato nello storage S3;
  • replicazione attiva facile da implementare;
  • clustering e sharding semplici senza Sentinel e altro software ausiliario.

Oltre 3.000 stelle e numerosi collaboratori su GitHub sembravano anche promettenti. L'applicazione è in fase di sviluppo attivo e supportata, come evidenziato dai commit, dall'interazione nelle issues e dai PR chiusi (accettati). Il feedback del manutentore principale è sempre cordiale e tempestivo. In breve, ci sono stati molti argomenti.

Migrazione e risultati

Nonostante il progetto di migrazione fosse un'operazione piuttosto azzardata (vista la novità di KeyDB), non avevamo molto da perdere. Infatti, ripristinare le modifiche è stato piuttosto veloce e semplice, dato che tutta l'infrastruttura è stata distribuita in Kubernetes e i meccanismi integrati Aggiornamento progressivo affrontano perfettamente tali compiti.

In sintesi, abbiamo preparato i modelli Helm, abbiamo cambiato l'applicazione nell'ambiente di test sulla nuova base di dati e abbiamo effettuato il rilascio, consegnando il tutto al team QA del cliente.

Sono iniziati i test, che sono durati circa una settimana e di cui non siamo entrati nei dettagli. Sappiamo solo che il cliente ha verificato le funzionalità standard di Redis utilizzando il driver PHP phpredis, e ha anche condotto il QA testing dell'interfaccia utente. Dopo di che ci è stato 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 non abbiamo apportato modifiche nemmeno alla configurazione: in sostanza, abbiamo semplicemente sostituito l'immagine utilizzata. Lo stesso vale per il monitoraggio e l'esportazione delle metriche in Prometheus: il più comune di essi funziona ottimamente con KeyDB senza alcuna modifica. Pertanto, si può affermare con certezza che, dal punto di vista operativo, si tratta di una migrazione semplicemente ideale.

Grazie a tutto ciò, dopo aver commutato l'applicazione su un nuovo DBMS, non è necessario apportare modifiche, e come "misura di stabilizzazione" è possibile lasciarlo funzionare così per un certo periodo. Tuttavia, se si desidera vedere un incremento delle prestazioni (o comunque dei cambiamenti), non bisogna dimenticare che predefinito il parametro KeyDB responsabile del multithreading (server-threads), è impostato su uno, cioè il DBMS funziona esattamente come Redis..

Dopo la commutazione, i test e un certo periodo di operatività sull'applicazione nuova (con KeyDB), abbiamo deciso di ripetere il test di carico utilizzando gli stessi parametri già impiegati per Redis. Quali sono stati i risultati?

Dal grafico del consumo della CPU è stato subito evidente che sono stati risolti i problemi con il "tetto" su un core: il processo ha iniziato a utilizzare le risorse disponibili:

KeyDB come [potenziale] sostituto di Redis

Successivamente, ho provato a "stressare" notevolmente l'applicazione e ho osservato un consumo fino a tre core...

Secondo New Relic, l'applicazione web ha mostrato un comportamento notevolmente più adeguato pur avendo la stessa carica. Alcuni dati sulla degradazione delle prestazioni sono comunque emersi, tuttavia, confrontando con il grafico simile sopra, puoi valutare tu stesso i progressi significativi:

KeyDB come [potenziale] sostituto di Redis

Il tempo di latenza del nuovo database (KeyDB) è peggiorato, ma è rimasto nei limiti accettabili:

KeyDB come [potenziale] sostituto di Redis

Nel grafico seguente è evidente che il numero di richieste alla KeyDB è simile:

KeyDB come [potenziale] sostituto di Redis

In sintesi, 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 (1000+). Nel nostro caso, però, l'applicazione web è riuscita a ridurre la latenza di Redis anche con un numero inferiore di connessioni (400+), mentre per KeyDB tale carico rimaneva accettabile.

Conclusioni

Questo esempio dimostra magnificamente la forza della comunità Open Source nello sviluppo dei progetti di cui è interessata. Su Internet ho incontrato una citazione eccellente, il cui significato generale si riduce a quanto segue: «Una grande azienda crea un prodotto interessante, rende alcune delle sue funzioni aperte, ma lascia a pagamento la parte più importante. La comunità lo utilizza e poi qualcuno si decide a fare un fork, implementando quelle stesse funzionalità a pagamento e aprendole a tutti». Ecco KeyDB — questo è proprio il caso.

Parlando della migrazione stessa, che è avvenuta sorprendentemente senza problemi, non abbiamo ricevuto un così significativo aumento delle prestazioni, quello che ci si potrebbe aspettare guardando i grafici degli autori di KeyDB… Tuttavia, questo è solo il nostro caso particolare, nel quale possono esserci molte deviazioni, comprese quelle legate alla famigerata architettura dell'applicazione (ad esempio, un numero enorme di comandi get in Redis invece di una variante più performante delle query aggregate mget…). Tuttavia, sono stati raggiunti risultati positivi, insieme a molte funzionalità utili che implementeremo nel prossimo futuro.

In generale, KeyDB sembra promettente: man mano che acquisiremo esperienza pratica con questo DBMS (e dobbiamo ancora farlo!) e che il progetto stesso si svilupperà, considereremo l'opportunità di utilizzarlo anche in altre situazioni.

Tuttavia, non bisogna considerare questo articolo come una guida (e tantomeno come un invito) a rinunciare completamente a Redis a favore di KeyDB. Nonostante la nostra esperienza positiva, è chiaro che non si tratta di una soluzione miracolosa. Il caso era piuttosto specifico: in particolare per risolvere un problema immediato in una situazione in cui era necessario farlo rapidamente e con costi minimi, questa soluzione ha funzionato. Sarà KeyDB utile nel tuo caso? Perlomeno, ora sai che tale opportunità potenziale esiste.

P.S.

Leggete anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster