Verso database senza server — come e perché

Ciao a tutti! Mi chiamo Nikolaj Golov. In passato ho lavorato per Avito e per sei anni ho guidato la Data Platform, occupandomi di tutti i database: analitici (Vertica, ClickHouse), streaming e OLTP (Redis, Tarantool, VoltDB, MongoDB, PostgreSQL). In questo periodo ho studiato un gran numero di database — dei più vari e insoliti, e con casi d'uso non standard.

Attualmente lavoro in ManyChat. In sostanza, è una startup — nuova, ambiziosa e in rapida crescita. E quando sono entrato in azienda, è sorto il classico quesito: "Quali database sul mercato delle DBMS e dei database dovrebbe considerare una giovane startup?".

In questo articolo, basato sulla mia presentazione al festival online RIT++2020, risponderò a questa domanda. La versione video della presentazione è disponibile su YouTube.

Verso database senza server — come e perché

Database noti nel 2020

Siamo nel 2020, guardandomi intorno ho notato tre tipi di database.

Il primo tipo — database OLTP classici: PostgreSQL, SQL Server, Oracle, MySQL. Sono stati scritti molto tempo fa, ma rimangono attuali, perché ben conosciuti dalla comunità di sviluppatori.

Il secondo tipo — database degli "anni 2000".Hanno cercato di allontanarsi dai modelli classici rinunciando a SQL, alle strutture tradizionali e all'ACID, grazie all'aggiunta di sharding incorporato e di altre funzionalità attraenti. Per esempio, ci sono Cassandra, MongoDB, Redis o Tarantool. Tutte queste soluzioni volevano offrire al mercato qualcosa di fondamentalmente nuovo e hanno trovato la loro nicchia, perché si sono dimostrate estremamente pratiche per determinate applicazioni. Questi database li etichetterò con il termine ombrello NOSQL.

"Gli anni 2000" sono finiti, ci siamo abituati ai database NOSQL, e il mondo, dal mio punto di vista, ha fatto il passo successivo — verso database gestiti. Questi database hanno un nucleo simile a quello dei classici database OLTP o dei nuovi NoSQL. Ma non hanno bisogno di DBA e DevOps e girano su server gestiti nel cloud. Per lo sviluppatore, è "semplicemente un database", che funziona da qualche parte, e come è stato installato sul server, chi ha configurato il server e chi lo aggiorna, non interessa a nessuno.

Esempi di tali database:

  • AWS RDS — un'interfaccia gestita su PostgreSQL/MySQL.
  • DynamoDB — un'alternativa AWS a un database basato su documenti, simile a Redis e MongoDB.
  • Amazon Redshift — un database analitico gestito.

Alla base ci sono vecchi database, ma rielaborati in un ambiente gestito, senza necessità di lavorare con l'hardware.

Nota. Gli esempi sono stati presi per l'ambiente AWS, ma anche i loro equivalenti esistono in Microsoft Azure, Google Cloud, o Yandex.Cloud.

Verso database senza server — come e perché

Cosa c'è di nuovo in tutto ciò? Nel 2020, nulla di tutto questo.

Concetto Serverless

La vera novità sul mercato nel 2020 è rappresentata dalle soluzioni serverless o senza server.

Proverò a spiegare cosa significa con l'esempio di un normale servizio o di un'applicazione backend.
Per distribuire un'applicazione backend tradizionale, acquistiamo o noleggiamo un server, copiamo il codice su di esso, pubblichiamo un endpoint e paghiamo regolarmente per l'affitto, l'elettricità e i servizi del data center. Questo è lo schema standard.

Esiste un modo diverso? Con i servizi serverless, sì.

Qual è il punto di questo approccio: non ci sono server, nemmeno un'istanza virtuale in affitto nel cloud. Per distribuire il servizio, copiamo il codice (funzioni) in un repository e pubblichiamo un endpoint. In seguito, paghiamo solo per ogni chiamata a questa funzione, ignorando completamente l'hardware su cui viene eseguita.

Proverò a illustrare questo approccio con delle immagini.
Verso database senza server — come e perché

Distribuzione classica. Abbiamo un servizio con un certo carico. Alziamo due istanze: server fisici o istanze in AWS. Queste istanze ricevono richieste esterne, che vengono elaborate lì.

Come si vede nell'immagine, i server sono utilizzati in modo diverso. Uno è utilizzato al 100%, ricevendo due richieste, mentre l'altro solo al 50% — in parte inattivo. Se arrivano non tre richieste, ma 30, l'intero sistema non reggerà il carico e inizierà a rallentare.

Verso database senza server — come e perché

Distribuzione senza server. In un ambiente serverless, un servizio simile non ha istanze né server. Esiste un certo pool di risorse pronte — piccoli container Docker preparati con il codice della funzione distribuita. Il sistema riceve richieste esterne e per ciascuna di esse il framework serverless attiva un piccolo container con il codice: elabora proprio quella richiesta e poi elimina il container.

Una richiesta — un container attivato, 1000 richieste — 1000 container. E la distribuzione su server fisici è già compito del fornitore di cloud. Questa è completamente gestita dal framework serverless. In questo concetto, paghiamo per ogni chiamata. Ad esempio, se arriva una chiamata al giorno — paghiamo per una chiamata, se ne arrivano un milione al minuto — paghiamo per un milione. O al secondo, anche questo succede.

Il concetto di pubblicazione di una funzione serverless si adatta a un servizio stateless. Se invece hai bisogno di un servizio statefull, allora aggiungiamo un database al servizio. In questo caso, quando si tratta di gestire lo stato, ciascuna funzione statefull legge e scrive semplicemente nel database. Inoltre, si può utilizzare un database di uno qualsiasi dei tre tipi descritti all'inizio dell'articolo.

Qual è il limite comune a tutti questi database? Sono i costi per un server cloud o fisico utilizzato continuamente (o per più server). Non importa se utilizziamo un database classico o gestito, se c'è un DevOps e un admin o meno, paghiamo comunque 24 ore su 24, 7 giorni su 7 per l'hardware, l'elettricità e l'affitto del data center. Se abbiamo un database classico, paghiamo per master e slave. Se si tratta di un database shardato ad alta richiesta, paghiamo per 10, 20 o 30 server, e i costi sono costanti.

La presenza di server riservati costantemente nella struttura dei costi è stata in passato considerata un male necessario. I database tradizionali presentano anche altre complessità, come i limiti sul numero di connessioni, la scalabilità limitata e il consenso geo-distribuito: alcune di queste possono essere risolte in determinati database, ma non tutte insieme e non in modo perfetto.

Database serverless - teoria

Domanda del 2020: è possibile rendere un database serverless? Tutti hanno sentito parlare di backend serverless... proviamo allora a rendere serverless anche il database?

Questo sembra strano, perché un database è un servizio statefull, non molto adatto per un'infrastruttura serverless. Inoltre, lo stato di un database è estremamente grande: gigabyte, terabyte e nei database analitici anche petabyte. Non è così semplice farlo funzionare in container Docker leggeri.

D'altra parte, praticamente tutti i database moderni sono un'enorme quantità di logica e componenti: transazioni, verifica dell'integrità, procedure, dipendenze relazionali e molta logica. Una parte piuttosto grande della logica del database richiede uno stato abbastanza ridotto. I gigabyte e i terabyte sono utilizzati direttamente solo da una piccola parte della logica del database, quella che riguarda l'esecuzione diretta delle query.

Di conseguenza, l'idea: se parte della logica consente un'esecuzione stateless, perché non suddividere il database in parti Stateful e Stateless.

Serverless per soluzioni OLAP

Vediamo come potrebbe apparire la suddivisione del database in parti Stateful e Stateless attraverso esempi pratici.

Verso database senza server — come e perché

Ad esempio, abbiamo un database analitico: dati esterni (cilindro rosso a sinistra), processo ETL che carica i dati nel database e analista che invia richieste SQL al database. Questo è uno schema classico di lavoro di un data warehouse.

In questo schema, per convenzione, l'ETL viene eseguito una sola volta. Da quel momento in poi, è necessario pagare continuamente per i server su cui opera il database con i dati caricati dall'ETL, in modo da avere un luogo dove inviare le richieste.

Esaminiamo un approccio alternativo, realizzato nel database AWS Athena Serverless. Qui non ci sono macchine dedicate in modo permanente su cui sono archiviati i dati caricati. Al contrario:

  • L'utente invia una richiesta SQL ad Athena. L'ottimizzatore di Athena analizza la richiesta SQL e cerca nello storage dei metadati (Metadata) i dati specifici necessari per soddisfare la richiesta.
  • L'ottimizzatore, sulla base dei dati raccolti, estrae i dati necessari da fonti esterne in uno storage temporaneo (database temporaneo).
  • Nel database temporaneo viene eseguita la richiesta SQL dell'utente e il risultato viene restituito all'utente.
  • Il database temporaneo viene svuotato e le risorse vengono liberate.

In questa architettura paghiamo solo per il processo di esecuzione della richiesta. Nessuna richiesta — nessun costo.

Verso database senza server — come e perché

Questo è un approccio operativo e viene realizzato non solo in Athena Serverless, ma anche in Redshift Spectrum (in AWS).

Dall'esempio di Athena, è evidente che il database Serverless funziona con richieste reali di decine e centinaia di terabyte di dati. Per centinaia di terabyte saranno necessari centinaia di server, ma non dobbiamo pagare per loro — paghiamo per le richieste. La velocità di ogni richiesta è (molto) bassa rispetto ai database analitici specializzati come Vertica, ma non paghiamo i periodi di inattività.

Tale database è applicabile per richieste analitiche ad-hoc rare. Ad esempio, quando decidiamo spontaneamente di verificare un'ipotesi su un gigantesco volume di dati. Per questi casi, Athena è perfetta. Per le richieste regolari, questo sistema diventa costoso. In tal caso, è consigliabile memorizzare i dati in una soluzione specializzata.

Serverless per soluzioni OLTP

Nel precedente esempio sono stati trattati compiti OLAP (analitici). Ora esaminiamo compiti OLTP.

Immaginiamo un PostgreSQL o un MySQL scalabile. Creiamo un'istanza gestita di PostgreSQL o MySQL con risorse minime. Quando l'istanza subirà un carico maggiore, collegheremo repliche aggiuntive su cui distribuiamo parte del carico di lettura. Se non ci sono richieste e carico — disconnettiamo le repliche. La prima istanza è il master, mentre le altre sono repliche.

Questa idea è realizzata in un database chiamato Aurora Serverless AWS. Il principio è semplice: il proxy fleet accoglie le richieste delle applicazioni esterne. Vedendo un aumento del carico, assegna risorse computazionali da istanze minime precedentemente attivate — la connessione avviene il più rapidamente possibile. Anche la disconnessione delle istanze avviene in modo simile.

All'interno di Aurora esiste il concetto di Aurora Capacity Unit, ACU. Questo è (in termini generali) un'istanza (server). Ogni singolo ACU può essere master o slave. Ogni Capacity Unit ha la propria memoria operativa, processore e disco minimi. Di conseguenza, un master e le altre repliche sono solo in lettura.

Il numero di Aurora Capacity Units attivi è un parametro configurabile. Il numero minimo può essere uno o zero (in tal caso, il database non funziona se non ci sono richieste).

Verso database senza server — come e perché

Quando il database riceve richieste, il proxy fleet attiva gli Aurora Capacity Units, aumentando le risorse di sistema. La possibilità di aumentare e diminuire le risorse consente al sistema di "giocare" con le risorse: disattivare automaticamente singoli ACU (sostituendoli con nuovi) e applicare su quelle disattivate tutti gli aggiornamenti attuali.

Il database Aurora Serverless può scalare il carico di lettura. Ma nella documentazione non viene detto esplicitamente. Potrebbe sorgere l'impressione che possano attivare un multi-master. Non c'è alcun trucco.

Questo database è molto adatto per non spendere enormi somme per sistemi con accesso imprevedibile. Ad esempio, nella creazione di MVP o siti web di marketing, di solito non ci aspettiamo un carico stabile. Pertanto, in assenza di accesso, non paghiamo per le istanze. Quando si verifica improvvisamente un carico, ad esempio dopo una conferenza o una campagna pubblicitaria, le folle di persone accedono al sito e il carico aumenta drasticamente, Aurora Serverless accetta automaticamente questo carico e collega rapidamente le risorse mancanti (ACU). Successivamente, la conferenza termina, tutti dimenticano il prototipo, i server (ACU) si spengono e le spese scendono a zero — comodo.

Questa soluzione non è adatta per carichi di lavoro stabili e elevati, perché non è in grado di scalare il carico di scrittura. Tutti questi collegamenti e disconnessioni delle risorse avvengono nel momento noto come 'scale point' — il momento in cui il database non è mantenuto da una transazione, né da tabelle temporanee. Ad esempio, nel corso della settimana, lo scale point potrebbe non verificarsi affatto, e il database lavora con risorse fisse e semplicemente non può né espandersi né contrarsi.

Non c'è magia — è un normale PostgreSQL. Ma il processo di aggiunta e disconnessione delle macchine è parzialmente automatizzato.

Serverless by design

Aurora Serverless è un vecchio database riscritto per il cloud, per sfruttare i singoli vantaggi del Serverless. E ora parlerò di un database che è stato inizialmente scritto per il cloud, secondo l'approccio serverless — Serverless-by-design. È stato subito sviluppato senza presupporre che funzionasse su server fisici.

Questo database si chiama Snowflake. Esso comprende tre blocchi chiave.

Verso database senza server — come e perché

Il primo è il blocco dei metadati. È un servizio in-memory veloce che si occupa di sicurezza, metadati, transazioni e ottimizzazione delle query (nell'illustrazione a sinistra).

Il secondo blocco è composto da numerosi cluster computazionali virtuali per i calcoli (nell'illustrazione — un insieme di cerchi blu).

Il terzo blocco è un sistema di archiviazione dati basato su S3. S3 è uno spazio di archiviazione oggetti illimitato in AWS, simile a un Dropbox illimitato per le aziende.

Vediamo come funziona Snowflake, ipotizzando un avvio a freddo. Cioè, il database esiste, i dati sono stati caricati, ma non ci sono query in corso. Di conseguenza, se non ci sono query sul database, abbiamo un servizio Metadata in-memory rapido attivo (il primo blocco). E abbiamo uno storage S3 dove si trovano i dati delle tabelle, suddivisi in cosiddette micro-partizioni. Per semplificare: se nella tabella ci sono affari, le micro-partizioni corrispondono ai giorni degli affari. Ogni giorno è una micro-partizione separata, un file separato. E quando il database funziona in questo modo, paghi solo per lo spazio occupato dai dati. Inoltre, la tariffa per lo spazio è molto bassa (soprattutto considerando la significativa compressione). Anche il servizio di metadati funziona costantemente, ma per ottimizzare le query non servono molte risorse, quindi si può considerare un servizio condizionatamente gratuito.

Immaginiamo ora che un utente abbia effettuato una richiesta SQL al nostro database. La richiesta SQL viene immediatamente inviata per l'elaborazione al servizio Metadata. Di conseguenza, ricevuta la richiesta, questo servizio analizza la richiesta, i dati disponibili, i diritti dell'utente e, se tutto è in ordine, elabora un piano di esecuzione per la query.

Successivamente, il servizio avvia un cluster di calcolo. Un cluster di calcolo è un insieme di server che eseguono calcoli. Cioè, questo cluster può contenere 1 server, 2 server, 4, 8, 16, 32 — quanti ne vuoi. Invi un'query e questo cluster inizia a essere avviato istantaneamente. Ciò richiede realmente pochi secondi.

Verso database senza server — come e perché

Dopo che il cluster è stato avviato, le micro-partizioni necessarie per elaborare la tua richiesta iniziano a essere copiate nel cluster da S3. Supponiamo, ad esempio, che per eseguire una query SQL siano necessarie due partizioni da una tabella e una da un'altra. In tal caso, verranno copiate nel cluster solo le tre partizioni richieste, e non tutte le tabelle in blocco. Per questo motivo, e proprio perché tutto si trova all'interno di un unico data center collegato con canali molto veloci, l'intero processo di trasferimento avviene in modo molto rapido: in pochi secondi, raramente in minuti, se non si tratta di query eccezionalmente complesse. Le micro-partizioni vengono quindi copiate nel cluster di calcolo e, al termine, la query SQL viene eseguita su questo cluster di calcolo. Il risultato di questa query può consistere in una singola riga, diverse righe o una tabella — che vengono restituite all'utente per essere scaricate, visualizzate nel proprio strumento BI o utilizzate in altro modo.

Ogni query SQL può non solo calcolare aggregati dai dati precedentemente caricati, ma anche caricare/formare nuovi dati nel database. Ad esempio, può trattarsi di una query che esegue l'inserimento di nuovi record in un'altra tabella, il che porta alla creazione di una nuova partizione nel cluster di calcolo, che viene automaticamente salvata nell'archivio S3 unico.

Lo scenario descritto sopra, dall'arrivo dell'utente fino all'avvio del cluster, al caricamento dei dati, all'esecuzione delle query e all'ottenimento dei risultati, viene fatturato a una tariffa in base ai minuti di utilizzo del cluster di calcolo virtuale attivato, il warehouse virtuale. La tariffa varia a seconda della zona AWS e delle dimensioni del cluster, ma in media è di alcuni dollari all'ora. Un cluster di quattro macchine costa il doppio rispetto a uno di due macchine, e uno di otto macchine costa ancora il doppio. Sono disponibili opzioni da 16, 32 macchine, a seconda della complessità delle query. Ma paghi solo per i minuti in cui il cluster è realmente attivo, perché quando non ci sono query, puoi semplicemente rilassarti e, dopo 5-10 minuti di attesa (un parametro configurabile), si spegnerà da solo, libererà risorse e diventerà gratuito.

È assolutamente realistico uno scenario in cui inviate una richiesta, il cluster si attiva, per così dire, dopo un minuto, impiega un altro minuto per calcolare, poi cinque minuti per spegnersi, e alla fine pagate per sette minuti di lavoro di questo cluster, e non per mesi o anni.

Il primo scenario descriveva l'uso di Snowflake in modalità monoutente. Ora immaginiamo che ci siano molti utenti, che è già più vicino a uno scenario reale.

Supponiamo di avere molti analisti e report di Tableau che bombardano continuamente il nostro database con un grande numero di semplici query SQL analitiche.

Oltre a ciò, supponiamo che abbiamo data scientist ingegnosi che cercano di fare cose stravaganti con i dati, operando su decine di terabyte, analizzando miliardi e trilioni di righe di dati.

Per i due tipi di carico descritti sopra, Snowflake consente di attivare diversi cluster di calcolo indipendenti di varie potenze. Questi cluster di calcolo operano in modo indipendente, ma con dati coerenti condivisi.

Per un gran numero di richieste leggere, è possibile attivare 2-3 piccoli cluster, ciascuno di dimensioni, per così dire, 2 macchine. Questo comportamento è realizzabile anche tramite impostazioni automatiche. Cioè, dici: "Snowflake, attiva un piccolo cluster. Se il carico su di esso supera un certo parametro, attiva un secondo e un terzo simile. Quando il carico inizia a diminuire, spegni i cluster superflui." In questo modo, indipendentemente da quanti analisti arrivano e iniziano a visualizzare i report, ci sono sempre risorse sufficienti.

Tuttavia, se gli analisti dormono e non si visualizzano report, i cluster possono spegnersi completamente, e smettete di pagare per essi.

Inoltre, per le richieste pesanti (da parte dei data scientist), potete attivare un cluster molto grande di circa 32 macchine. Anche questo cluster sarà pagato solo per i minuti e le ore in cui il vostro gigante sta eseguendo una query.

La possibilità descritta sopra consente di suddividere i carichi non solo in 2, ma anche in più tipi di carico (ETL, monitoraggio, materializzazione dei report,…).

Faremo un riepilogo su Snowflake. La base combina un'idea elegante e una realizzazione funzionale. In ManyChat utilizziamo Snowflake per analizzare tutti i dati disponibili. I nostri cluster non sono tre, come nell'esempio, ma da 5 a 9, di varie dimensioni. Abbiamo cluster convenzionali di 16 macchine, cluster di 2 macchine, e anche piccolissimi cluster di 1 macchina per alcune attività. Questi distribuiscono efficacemente il carico e ci permettono di risparmiare significativamente.

La base scala efficacemente il carico di lettura e scrittura. Questa è una differenza enorme e un grande progresso rispetto alla 'Aurora', che gestiva solo il carico di lettura. Snowflake consente di scalare anche il carico di scrittura con questi cluster computazionali. Come ho già accennato, in ManyChat utilizziamo diversi cluster, i cluster più piccoli e super piccoli sono principalmente impiegati per l'ETL, per il caricamento dei dati. Gli analisti operano su cluster medi, che non sono affatto influenzati dal carico dell'ETL, quindi funzionano molto rapidamente.

Di conseguenza, la base è ben adatta per le attività OLAP. Tuttavia, sfortunatamente, non è ancora adatta per i carichi OLTP. In primo luogo, questa base è a colonne, con tutte le conseguenze del caso. In secondo luogo, l'approccio stesso, in cui per ogni richiesta si solleva un cluster computazionale e lo si alimenta di dati, purtroppo non è ancora sufficientemente veloce per i carichi OLTP. Secondi di attesa per attività OLAP sono accettabili, mentre per le attività OLTP sono inaccettabili; sarebbe meglio 100 ms, e ancora meglio 10 ms.

Risultato

Le basi database senza server sono possibili grazie alla separazione della base in parti Stateless e Stateful. Avrete notato che in tutti gli esempi forniti, la parte Stateful è, per così dire, lo storage delle micro-partizioni in S3, mentre la parte Stateless è l'ottimizzatore, il lavoro con i meta-dati, e la gestione delle questioni di sicurezza, che possono essere sollevate come servizi leggeri Stateless indipendenti.

L'esecuzione delle query SQL può essere considerata anch'essa come servizi con uno stato leggero, che possono apparire in modalità senza server, come i cluster computazionali di Snowflake, scaricare solo i dati necessari, eseguire la query e "spegnersi".

Le basi serverless di livello produttivo sono già disponibili per l'uso, e funzionano. Queste basi serverless sono già pronte ad affrontare compiti OLAP. Sfortunatamente, per i compiti OLTP sono utilizzate... con delle sfide, poiché ci sono delle limitazioni. Da un lato, questo è un problema. Ma, dall'altro lato, è un'opportunità. Forse qualche lettore troverà un modo per rendere completamente serverless una base OLTP, senza limitazioni di Aurora.

Spero che vi sia piaciuto. Verso un futuro serverless 🙂

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