Sulla strada verso i database serverless: come e perché

Ciao a tutti! Il mio nome è Golov Nikolay. In precedenza, ho lavorato presso Avito e ho gestito la Data Platform per sei anni, ovvero ho lavorato su tutti i database: analitici (Vertica, ClickHouse), streaming e OLTP (Redis, Tarantool, VoltDB, MongoDB, PostgreSQL). Durante questo periodo, mi sono occupato di un gran numero di database, molto diversi e insoliti, e di casi non standard del loro utilizzo.

Attualmente lavoro presso ManyChat. In sostanza, questa è una startup: nuova, ambiziosa e in rapida crescita. E quando sono entrato in azienda per la prima volta, è sorta una domanda classica: "Cosa dovrebbe prendere una giovane startup ora dal mercato dei DBMS e dei database?"

In questo articolo, basato sul mio rapporto su festival online RIT++2020, risponderò a questa domanda. Una versione video del rapporto è disponibile all'indirizzo YouTube.

Sulla strada verso i database serverless: come e perché

Database comunemente noti 2020

È il 2020, mi sono guardato intorno e ho visto tre tipi di database.

Primo tipo - database OLTP classici: PostgreSQL, SQL Server, Oracle, MySQL. Sono stati scritti molto tempo fa, ma sono ancora rilevanti perché sono molto familiari alla comunità degli sviluppatori.

Il secondo tipo è basi da "zero". Hanno cercato di allontanarsi dai modelli classici abbandonando SQL, strutture tradizionali e ACID, aggiungendo sharding integrato e altre funzionalità interessanti. Ad esempio, questo è Cassandra, MongoDB, Redis o Tarantool. Tutte queste soluzioni volevano offrire al mercato qualcosa di fondamentalmente nuovo e occupavano la loro nicchia perché si rivelavano estremamente convenienti per determinati compiti. Indicherò questi database con il termine generico NOSQL.

Gli “zero” sono finiti, ci siamo abituati ai database NOSQL e il mondo, dal mio punto di vista, ha fatto il passo successivo: database gestiti. Questi database hanno lo stesso nucleo dei classici database OLTP o dei nuovi NoSQL. Ma non hanno bisogno di DBA e DevOps e funzionano su hardware gestito nei cloud. Per uno sviluppatore, questa è "solo una base" che funziona da qualche parte, ma a nessuno importa come è installata sul server, chi ha configurato il server e chi lo aggiorna.

Esempi di tali database:

  • AWS RDS è un wrapper gestito per PostgreSQL/MySQL.
  • DynamoDB è un analogo AWS di un database basato su documenti, simile a Redis e MongoDB.
  • Amazon Redshift è un database analitico gestito.

Si tratta fondamentalmente di vecchi database, ma cresciuti in un ambiente gestito, senza la necessità di lavorare con l'hardware.

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

Sulla strada verso i database serverless: come e perché

Cosa c'è di nuovo in questo? Nel 2020, niente di tutto questo.

Concetto senza server

La vera novità sul mercato nel 2020 sono le soluzioni serverless o serverless.

Cercherò di spiegare cosa significa utilizzando l'esempio di un servizio regolare o di un'applicazione backend.
Per implementare una normale applicazione backend, acquistiamo o affittiamo un server, copiamo il codice su di esso, pubblichiamo l'endpoint all'esterno e paghiamo regolarmente l'affitto, l'elettricità e i servizi del data center. Questo è lo schema standard.

C'è un altro modo? Con i servizi serverless puoi.

Qual è il fulcro di questo approccio: non c'è nessun server, non c'è nemmeno il noleggio di un'istanza virtuale nel cloud. Per distribuire il servizio, copiare il codice (funzioni) nel repository e pubblicarlo sull'endpoint. Quindi paghiamo semplicemente per ogni chiamata a questa funzione, ignorando completamente l'hardware su cui viene eseguita.

Cercherò di illustrare questo approccio con le immagini.
Sulla strada verso i database serverless: come e perché

Distribuzione classica. Abbiamo un servizio con un certo carico. Creiamo due istanze: server fisici o istanze in AWS. Le richieste esterne vengono inviate a queste istanze e lì elaborate.

Come puoi vedere nell'immagine, i server non sono distribuiti equamente. Uno è utilizzato al 100%, ci sono due richieste e uno è solo al 50% - parzialmente inattivo. Se non arrivano tre richieste, ma 30, l'intero sistema non sarà in grado di far fronte al carico e inizierà a rallentare.

Sulla strada verso i database serverless: come e perché

Distribuzione senza server. In un ambiente serverless, tale servizio non dispone di istanze o server. Esiste un certo pool di risorse riscaldate: piccoli contenitori Docker preparati con codice funzione distribuito. Il sistema riceve richieste esterne e per ognuna di esse il framework serverless genera un piccolo contenitore con codice: elabora questa particolare richiesta e uccide il contenitore.

Una richiesta - un contenitore raccolto, 1000 richieste - 1000 contenitori. E l’implementazione sui server hardware è già opera del fornitore di servizi cloud. È completamente nascosto dal framework serverless. In questo concetto paghiamo per ogni chiamata. Ad esempio, arrivava una chiamata al giorno - abbiamo pagato per una chiamata, ne arrivavano un milione al minuto - abbiamo pagato un milione. Oppure in un secondo, accade anche questo.

Il concetto di pubblicazione di una funzione serverless è adatto per un servizio stateless. E se hai bisogno di un servizio statefull (statale), aggiungiamo un database al servizio. In questo caso, quando si tratta di lavorare con lo stato, ciascuna funzione statefull semplicemente scrive e legge dal database. Inoltre, da un database di uno qualsiasi dei tre tipi descritti all'inizio dell'articolo.

Qual è il limite comune di tutti questi database? Questi sono i costi di un server cloud o hardware costantemente utilizzato (o più server). Non importa se utilizziamo un database classico o gestito, se abbiamo Devops e un amministratore oppure no, paghiamo comunque l’hardware, l’elettricità e il noleggio del data center 24 ore su 7, 10 giorni su 20. Se abbiamo una base classica, paghiamo master e slave. Se si tratta di un database frammentato molto caricato, paghiamo 30, XNUMX o XNUMX server e paghiamo costantemente.

La presenza di server permanentemente riservati nella struttura dei costi era precedentemente percepita come un male necessario. I database convenzionali presentano anche altre difficoltà, come limiti al numero di connessioni, restrizioni di scala, consenso geo-distribuito: possono in qualche modo essere risolti in alcuni database, ma non tutti in una volta e non idealmente.

Database senza server: teoria

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

Ciò suona strano, perché il database è un servizio statefull, poco adatto per infrastrutture serverless. Allo stesso tempo, lo stato del database è molto grande: gigabyte, terabyte e nei database analitici anche petabyte. Non è così facile allevarlo in contenitori Docker leggeri.

D'altra parte, quasi tutti i database moderni contengono un'enorme quantità di logica e componenti: transazioni, coordinamento dell'integrità, procedure, dipendenze relazionali e molta logica. Per gran parte della logica del database, è sufficiente uno stato piccolo. Gigabyte e Terabyte vengono utilizzati direttamente solo da una piccola parte della logica del database coinvolta nell'esecuzione diretta delle query.

Di conseguenza, l’idea è: se parte della logica consente l’esecuzione stateless, perché non dividere la base in parti Stateful e Stateless.

Serverless per soluzioni OLAP

Vediamo come potrebbe apparire la suddivisione di un database in parti Stateful e Stateless utilizzando esempi pratici.

Sulla strada verso i database serverless: come e perché

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

In questo schema, l'ETL viene eseguito in modo condizionale una volta. Quindi è necessario pagare costantemente i server su cui viene eseguito il database con dati riempiti con ETL, in modo che ci sia qualcosa a cui inviare query.

Diamo un'occhiata a un approccio alternativo implementato in AWS Athena Serverless. Non esiste un hardware dedicato in modo permanente su cui vengono archiviati i dati scaricati. Invece di questo:

  • L'utente invia una query SQL ad Athena. L'ottimizzatore Athena analizza la query SQL e cerca nell'archivio dei metadati (Metadati) i dati specifici necessari per eseguire la query.
  • L'ottimizzatore, sulla base dei dati raccolti, scarica i dati necessari da fonti esterne nella memoria temporanea (database temporaneo).
  • Una query SQL dell'utente viene eseguita nella memoria temporanea e il risultato viene restituito all'utente.
  • La memoria temporanea viene cancellata e le risorse vengono rilasciate.

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

Sulla strada verso i database serverless: come e perché

Questo è un approccio funzionante ed è implementato non solo in Athena Serverless, ma anche in Redshift Spectrum (in AWS).

L'esempio di Athena mostra che il database Serverless funziona su query reali con decine e centinaia di Terabyte di dati. Centinaia di terabyte richiederanno centinaia di server, ma non dobbiamo pagarli: 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 rare query analitiche ad hoc. Ad esempio, quando decidiamo spontaneamente di verificare un'ipotesi su una quantità enorme di dati. Athena è perfetta per questi casi. Per le richieste regolari, un tale sistema è costoso. In questo caso, memorizzare nella cache i dati in una soluzione specializzata.

Serverless per soluzioni OLTP

L'esempio precedente esaminava le attività OLAP (analitiche). Consideriamo ora le attività OLTP.

Immaginiamo PostgreSQL o MySQL scalabili. Creiamo un'istanza gestita regolare PostgreSQL o MySQL con risorse minime. Quando l'istanza riceverà più carico, collegheremo repliche aggiuntive alle quali distribuiremo parte del carico di lettura. Se non ci sono richieste o carichi, disattiviamo le repliche. La prima istanza è il master e il resto sono repliche.

Questa idea è implementata in un database chiamato Aurora Serverless AWS. Il principio è semplice: le richieste provenienti da applicazioni esterne vengono accettate dalla flotta proxy. Vedendo aumentare il carico, alloca le risorse di elaborazione da istanze minime preriscaldate: la connessione viene stabilita il più rapidamente possibile. La disabilitazione delle istanze avviene allo stesso modo.

All'interno di Aurora esiste il concetto di Aurora Capacità Unit, ACU. Questa è (condizionatamente) un'istanza (server). Ciascuna ACU specifica può essere un master o uno slave. Ciascuna unità di capacità ha la propria RAM, processore e disco minimo. Di conseguenza, uno è master, gli altri sono repliche di sola lettura.

Il numero di queste unità di capacità Aurora in funzione è un parametro configurabile. La quantità minima può essere uno o zero (in questo caso il database non funziona se non ci sono richieste).

Sulla strada verso i database serverless: come e perché

Quando la base riceve richieste, la flotta proxy aumenta le AuroraCapacityUnits, aumentando le risorse prestazionali del sistema. La capacità di aumentare e diminuire le risorse consente al sistema di “destreggiarsi” tra le risorse: visualizzare automaticamente le singole ACU (sostituendole con nuove) e distribuire tutti gli aggiornamenti correnti alle risorse ritirate.

La base Aurora Serverless può scalare il carico di lettura. Ma la documentazione non lo dice direttamente. Potrebbe sembrare che possano sollevare un multi-master. Non c'è magia.

Questo database è particolarmente adatto per evitare di spendere ingenti somme di denaro su sistemi con accesso imprevedibile. Ad esempio, quando creiamo MVP o siti di biglietti da visita di marketing, di solito non ci aspettiamo un carico stabile. Di conseguenza, se non c'è accesso, non pagheremo le istanze. Quando si verifica un carico imprevisto, ad esempio dopo una conferenza o una campagna pubblicitaria, folle di persone visitano il sito e il carico aumenta notevolmente, Aurora Serverless prende automaticamente questo carico e collega rapidamente le risorse mancanti (ACU). Poi la conferenza passa, tutti si dimenticano del prototipo, i server (ACU) si oscurano e i costi scendono a zero: conveniente.

Questa soluzione non è adatta per carichi elevati stabili perché non ridimensiona il carico di scrittura. Tutte queste connessioni e disconnessioni di risorse si verificano nel cosiddetto "punto di scala", un punto nel tempo in cui il database non è supportato da una transazione o da tabelle temporanee. Ad esempio, entro una settimana il punto di scala potrebbe non verificarsi e la base funziona con le stesse risorse e semplicemente non può espandersi o contrarsi.

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

Serverless in base alla progettazione

Aurora Serverless è un vecchio database riscritto per il cloud per sfruttare alcuni dei vantaggi di Serverless. E ora ti parlerò della base, originariamente scritta per il cloud, per l'approccio serverless: Serverless-by-design. È stato sviluppato immediatamente senza il presupposto che sarebbe stato eseguito su server fisici.

Questa base si chiama Snowflake. Ha tre blocchi chiave.

Sulla strada verso i database serverless: come e perché

Il primo è un blocco di metadati. Si tratta di un servizio in memoria veloce che risolve problemi di sicurezza, metadati, transazioni e ottimizzazione delle query (mostrato nell'illustrazione a sinistra).

Il secondo blocco è un insieme di cluster di calcolo virtuale per i calcoli (nell'illustrazione c'è una serie di cerchi blu).

Il terzo blocco è un sistema di archiviazione dati basato su S3. S3 è l'archiviazione di oggetti adimensionali in AWS, una sorta di Dropbox adimensionale per le aziende.

Vediamo come funziona Snowflake, ipotizzando un avvio a freddo. Cioè, c'è un database, i dati vengono caricati al suo interno, non ci sono query in esecuzione. Di conseguenza, se non ci sono richieste al database, abbiamo attivato il servizio veloce di metadati in memoria (primo blocco). E abbiamo lo storage S3, dove vengono archiviati i dati delle tabelle, suddivisi nelle cosiddette micropartizioni. Per semplicità: se la tabella contiene transazioni, allora le micropartizioni sono i giorni delle transazioni. Ogni giorno è una micropartizione separata, un file separato. E quando il database funziona in questa modalità, paghi solo lo spazio occupato dai dati. Inoltre, la tariffa per posto è molto bassa (soprattutto se si tiene conto della notevole compressione). Anche il servizio di metadati funziona costantemente, ma non sono necessarie molte risorse per ottimizzare le query e il servizio può essere considerato shareware.

Ora immaginiamo che un utente sia arrivato al nostro database e abbia inviato una query SQL. La query SQL viene immediatamente inviata al servizio Metadati per l'elaborazione. Di conseguenza, dopo aver ricevuto una richiesta, questo servizio analizza la richiesta, i dati disponibili, i permessi dell'utente e, se tutto va bene, elabora un piano per l'elaborazione della richiesta.

Successivamente, il servizio avvia il lancio del cluster di elaborazione. Un cluster di elaborazione è un cluster di server che eseguono calcoli. Cioè, questo è un cluster che può contenere 1 server, 2 server, 4, 8, 16, 32, quanti ne vuoi. Lancia una richiesta e il lancio di questo cluster inizia immediatamente. Ci vogliono davvero pochi secondi.

Sulla strada verso i database serverless: come e perché

Successivamente, dopo l'avvio del cluster, le micropartizioni necessarie per elaborare la richiesta iniziano a essere copiate nel cluster da S3. Immaginiamo cioè che per eseguire una query SQL siano necessarie due partizioni da una tabella e una dalla seconda. In questo caso, nel cluster verranno copiate solo le tre partizioni necessarie e non tutte le tabelle. Ecco perché, e proprio perché tutto si trova all'interno di un data center e collegato tramite canali molto veloci, l'intero processo di trasferimento avviene molto rapidamente: in secondi, molto raramente in minuti, a meno che non si tratti di richieste mostruose. Di conseguenza, le micropartizioni vengono copiate nel cluster di calcolo e, al termine, la query SQL viene eseguita su questo cluster di calcolo. Il risultato di questa richiesta può essere una riga, più righe o una tabella: vengono inviati esternamente all'utente in modo che possa scaricarlo, visualizzarlo nel suo strumento BI o utilizzarlo in altro modo.

Ogni query SQL può non solo leggere aggregati da dati caricati in precedenza, ma anche caricare/generare nuovi dati nel database. Cioè, può essere una query che, ad esempio, inserisce nuovi record in un'altra tabella, il che porta alla comparsa di una nuova partizione sul cluster di calcolo, che, a sua volta, viene automaticamente salvata in un unico archivio S3.

Lo scenario sopra descritto, dall'arrivo dell'utente alla creazione del cluster, al caricamento dei dati, all'esecuzione delle query, all'ottenimento dei risultati, viene pagato in base alla tariffa per minuti di utilizzo del cluster di calcolo virtuale sollevato, magazzino virtuale. La tariffa varia a seconda della zona AWS e delle dimensioni del cluster, ma in media è di pochi dollari l'ora. Un cluster di quattro macchine è due volte più costoso di un cluster di due macchine, mentre un cluster di otto macchine è ancora due volte più costoso. Sono disponibili opzioni da 16, 32 macchine, a seconda della complessità delle richieste. Ma paghi solo per quei minuti in cui il cluster è effettivamente in esecuzione, perché quando non ci sono richieste, ti togli le mani e dopo 5-10 minuti di attesa (un parametro configurabile) si spegnerà da solo, liberare risorse e diventare liberi.

Uno scenario del tutto realistico è quando invii una richiesta, il cluster si apre, relativamente parlando, in un minuto, conta un altro minuto, poi cinque minuti per spegnersi, e finisci per pagare sette minuti di funzionamento di questo cluster, e non per mesi e anni.

Il primo scenario descriveva l'utilizzo di Snowflake in un'impostazione per utente singolo. Ora immaginiamo che ci siano molti utenti, il che è più vicino allo scenario reale.

Diciamo che abbiamo molti analisti e report di Tableau che bombardano costantemente il nostro database con un gran numero di semplici query SQL analitiche.

Inoltre, diciamo che abbiamo data scientist inventivi che stanno cercando di fare cose mostruose con i dati, operare con decine di terabyte, analizzare miliardi e trilioni di righe di dati.

Per le due tipologie di carico di lavoro sopra descritte, Snowflake consente di creare diversi cluster di calcolo indipendenti di diversa capacità. Inoltre, questi cluster informatici funzionano in modo indipendente, ma con dati comuni coerenti.

Per un gran numero di query leggere, puoi generare 2-3 piccoli cluster, circa 2 macchine ciascuno. Questo comportamento può essere implementato, tra le altre cose, utilizzando le impostazioni automatiche. Quindi dici: “Fiocco di neve, solleva un piccolo grappolo. Se il carico su di esso aumenta al di sopra di un determinato parametro, aumenta un secondo, terzo simile. Quando il carico comincia a diminuire, estinguere l’eccesso”. In modo che, indipendentemente dal numero di analisti che vengono e iniziano a esaminare i report, tutti hanno risorse sufficienti.

Allo stesso tempo, se gli analisti dormono e nessuno guarda i report, i cluster potrebbero oscurarsi completamente e tu potresti smettere di pagarli.

Allo stesso tempo, per query pesanti (da Data Scientist), puoi creare un cluster molto grande per 32 macchine. Questo cluster verrà inoltre pagato solo per i minuti e le ore in cui la tua richiesta gigante è in esecuzione lì.

L'opportunità sopra descritta consente di suddividere non solo 2, ma anche più tipologie di carico di lavoro in cluster (ETL, monitoraggio, materializzazione report,...).

Riassumiamo Snowflake. La base combina una bella idea e un'implementazione realizzabile. In ManyChat utilizziamo Snowflake per analizzare tutti i dati in nostro possesso. Non abbiamo tre cluster, come nell’esempio, ma da 5 a 9, di dimensioni diverse. Disponiamo di modelli convenzionali da 16 macchine, 2 macchine e anche piccolissimi da 1 macchina per alcune attività. Distribuiscono con successo il carico e ci consentono di risparmiare molto.

Il database ridimensiona con successo il carico di lettura e scrittura. Questa è un'enorme differenza e un enorme passo avanti rispetto alla stessa "Aurora", che trasportava solo il carico di lettura. Snowflake ti consente di ridimensionare il carico di lavoro di scrittura con questi cluster di elaborazione. Cioè, come ho già detto, utilizziamo diversi cluster in ManyChat, i cluster piccoli e super piccoli vengono utilizzati principalmente per ETL, per caricare i dati. E gli analisti vivono già su cluster medi, che non sono assolutamente interessati dal carico ETL, quindi lavorano molto velocemente.

Di conseguenza, il database è particolarmente adatto per le attività OLAP. Tuttavia, sfortunatamente, non è ancora applicabile ai carichi di lavoro OLTP. Innanzitutto, questo database è a colonne, con tutte le conseguenze che ne conseguono. In secondo luogo, l'approccio stesso, quando per ogni richiesta, se necessario, si solleva un cluster di elaborazione e lo si inonda di dati, purtroppo non è ancora abbastanza veloce per i carichi OLTP. I secondi di attesa per le attività OLAP sono normali, ma per le attività OLTP sono inaccettabili; 100 ms sarebbero migliori o 10 ms sarebbero ancora migliori.

risultato

Un database serverless è possibile dividendo il database in parti Stateless e Stateful. Potresti aver notato che in tutti gli esempi precedenti, la parte Stateful memorizza, relativamente parlando, micropartizioni in S3 e Stateless è l'ottimizzatore, che lavora con i metadati e gestisce i problemi di sicurezza che possono essere sollevati come servizi Stateless leggeri e indipendenti.

L'esecuzione di query SQL può anche essere percepita come servizi light-state che possono apparire in modalità serverless, come i cluster di elaborazione Snowflake, scaricare solo i dati necessari, eseguire la query e "uscire".

I database a livello di produzione serverless sono già disponibili per l'uso e funzionano. Questi database serverless sono già pronti per gestire le attività OLAP. Sfortunatamente, vengono utilizzati per le attività OLTP... con sfumature, poiché esistono limitazioni. Da un lato, questo è un aspetto negativo. Ma d’altra parte questa è un’opportunità. Forse uno dei lettori troverà un modo per rendere un database OLTP completamente serverless, senza le limitazioni di Aurora.

Spero che tu l'abbia trovato interessante. Il serverless è il futuro :)

Fonte: habr.com

Aggiungi un commento