Come smettere di preoccuparsi e iniziare a vivere senza monolite

Come smettere di preoccuparsi e iniziare a vivere senza monolite

Tutti amiamo le storie. Ci piace sederci attorno al fuoco e parlare delle nostre vittorie passate, delle nostre battaglie o semplicemente della nostra esperienza lavorativa.

Oggi è proprio un giorno così. E anche se non sei al fuoco in questo momento, abbiamo una storia per te. La storia di come abbiamo iniziato a lavorare con lo storage su Tarantool.

Una volta la nostra azienda aveva un paio di “monoliti” e un “tetto” per tutti, al quale questi monoliti si stavano avvicinando lentamente ma inesorabilmente, limitando la fuga della nostra azienda, il nostro sviluppo. E c’era una chiara intesa: un giorno raggiungeremo duramente questo limite.

Oggi prevale l’ideologia di separare tutto e tutti, dalle attrezzature alla logica aziendale. Di conseguenza, ad esempio, abbiamo due controller di dominio praticamente indipendenti a livello di rete. E poi tutto era completamente diverso.

Oggi ci sono molti strumenti e strumenti per apportare modifiche sotto forma di CI/CD, K8S, ecc. Nel tempo “monolitico” non avevamo bisogno di così tante parole straniere. Bastava semplicemente correggere la “memoria” nel database.

Ma il tempo è passato e con esso il numero di richieste, a volte sparando RPS oltre le nostre capacità. Con l'ingresso nel mercato dei paesi della CSI, il carico sul processore del database del primo monolite non è sceso al di sotto del 90% e l'RPS è rimasto al livello di 2400. E questi non erano solo piccoli selettori, ma query pesanti con un un mucchio di controlli e JOIN che potrebbero essere eseguiti per quasi la metà dei dati sullo sfondo di un IO di grandi dimensioni.

Quando i saldi del Black Friday a tutti gli effetti iniziarono ad apparire sulla scena - e Wildberries fu uno dei primi a tenerli in Russia - la situazione divenne completamente triste. Dopotutto, il carico in questi giorni aumenta tre volte.
Oh, questi “tempi monolitici”! Sono sicuro che hai sperimentato qualcosa di simile e ancora non riesci a capire come ciò possa accaderti.

Cosa puoi fare: la moda è inerente alla tecnologia. Circa 5 anni fa, abbiamo dovuto ripensare uno di questi mod sotto forma di un sito esistente su .NET e server MS SQL, che memorizzava con cura tutta la logica del sito stesso. L'ho tenuto così attentamente che segare un simile monolite si è rivelato un piacere lungo e per niente facile.
Una piccola digressione.

In vari eventi dico: “se non hai visto un monolite, allora non sei cresciuto!” Mi interessa la tua opinione su questo argomento, scrivila nei commenti.

E il tuono ha colpito

Torniamo al nostro "falò". Per distribuire il carico di funzionalità “monolitiche”, abbiamo deciso di dividere il sistema in microservizi basati su tecnologie opensource. Perché, come minimo, sono più economici da scalare. E sapevamo al 100% che avremmo dovuto espanderci (e molto). Dopotutto, già a quel tempo era possibile entrare nei mercati dei paesi vicini e il numero di immatricolazioni, così come il numero di ordini, iniziarono a crescere ancora più fortemente.

Dopo aver analizzato i primi candidati al passaggio dal monolite ai microservizi, ci siamo resi conto che l'80% della scrittura in essi contenuta proviene dai sistemi di back office e la lettura dal front office. Innanzitutto, ciò riguardava un paio di sottosistemi importanti per noi: i dati dell'utente e un sistema per calcolare il costo finale della merce basato sulle informazioni su ulteriori sconti e coupon dei clienti.

Dentato. Ora è spaventoso da immaginare, ma oltre ai sottosistemi sopra menzionati, dal nostro monolite sono stati rimossi anche i cataloghi dei prodotti, un carrello degli utenti, un sistema di ricerca dei prodotti, un sistema di filtraggio per i cataloghi dei prodotti e vari tipi di sistemi di raccomandazione. Per il funzionamento di ciascuno di essi esistono classi separate di sistemi strettamente personalizzati, ma una volta vivevano tutti in una "casa".

Abbiamo immediatamente pianificato di trasferire i dati sui nostri clienti sul sistema condiviso. La rimozione della funzionalità per il calcolo del costo finale delle merci richiedeva una buona scalabilità per la lettura, poiché creava il maggior carico di RPS ed era la più difficile da implementare per il database (nel processo di calcolo sono coinvolti molti dati).

Di conseguenza, abbiamo elaborato uno schema che si adatta bene a Tarantool.

A quel tempo, per il funzionamento dei microservizi, furono scelti schemi per lavorare con diversi data center su macchine virtuali e hardware. Come mostrato nelle figure, le opzioni di replica di Tarantool sono state applicate sia in modalità master-master che master-slave.

Come smettere di preoccuparsi e iniziare a vivere senza monolite
Architettura. Opzione 1. Servizio all'utente

Al momento sono presenti 24 shard, ognuno dei quali ha 2 istanze (una per ogni DC), tutti in modalità master-master.

In cima al database ci sono le applicazioni che accedono alle repliche del database. Le applicazioni funzionano con Tarantool attraverso la nostra libreria personalizzata, che implementa l'interfaccia del driver Tarantool Go. Vede tutte le repliche e può lavorare con il maestro per leggere e scrivere. Essenzialmente, implementa il modello del set di repliche, che aggiunge la logica per la selezione delle repliche, l'esecuzione dei tentativi, un interruttore automatico e un limite di velocità.

In questo caso è possibile configurare la politica di selezione della replica nel contesto degli shard. Ad esempio, il girotondo.

Come smettere di preoccuparsi e iniziare a vivere senza monolite
Architettura. Opzione 2. Servizio per il calcolo del costo finale della merce

Qualche mese fa, la maggior parte delle richieste per il calcolo del costo finale della merce è andata a un nuovo servizio, che, in linea di principio, funziona senza database, ma qualche tempo fa tutto è stato elaborato al 100% da un servizio con Tarantool sotto il cofano.

Il database del servizio è costituito da 4 master in cui il sincronizzatore raccoglie i dati e ciascuno di questi master di replica distribuisce i dati alle repliche di sola lettura. Ogni master ha circa 15 repliche di questo tipo.

Sia nel primo che nel secondo schema, se un DC non è disponibile, l'applicazione può ricevere dati nel secondo.

Vale la pena notare che la replica in Tarantool è abbastanza flessibile e può essere configurata in fase di runtime. In altri sistemi sono sorte difficoltà. Ad esempio, la modifica dei parametri max_wal_senders e max_replication_slots in PostgreSQL richiede il riavvio della procedura guidata, che in alcuni casi può portare all'interruzione delle connessioni tra l'applicazione e il DBMS.

Cerca e trova!

Perché non lo abbiamo fatto “come le persone normali”, ma abbiamo scelto un modo atipico? Dipende da cosa è considerato normale. Molte persone generalmente creano un cluster da Mongo e lo distribuiscono su tre DC distribuiti geograficamente.

A quel tempo avevamo già due progetti Redis. La prima era una cache e la seconda era un archivio persistente per dati non troppo critici. È stato abbastanza difficile con lui, in parte per colpa nostra. A volte nella chiave c'erano volumi piuttosto grandi e di tanto in tanto il sito si ammalava. Abbiamo utilizzato questo sistema nella versione master-slave. E ci sono stati molti casi in cui è successo qualcosa al master e la replicazione si è interrotta.

Ciò significa che Redis è utile per le attività stateless, non per quelle stateful. In linea di principio, consentiva di risolvere la maggior parte dei problemi, ma solo se si trattava di soluzioni di valori-chiave con una coppia di indici. Ma Redis a quel tempo era piuttosto triste per la perseveranza e la replica. Inoltre, ci sono state lamentele sulle prestazioni.

Abbiamo pensato a MySQL e PostgreSQL. Ma il primo in qualche modo non ci ha preso piede, e il secondo è di per sé un prodotto piuttosto sofisticato e sarebbe inappropriato costruire servizi semplici su di esso.
Abbiamo provato RIAK, Cassandra e persino un database grafico. Queste sono tutte soluzioni abbastanza di nicchia che non erano adatte al ruolo di strumento universale generale per la creazione di servizi.

Alla fine abbiamo optato per Tarantool.

Ci siamo rivolti ad esso quando era nella versione 1.6. Ci interessava la simbiosi tra valore-chiave e la funzionalità di un database relazionale. Esistono indici secondari, transazioni e spazi, sono come tabelle, ma non semplici, in essi è possibile memorizzare diversi numeri di colonne. Ma la caratteristica killer di Tarantool erano gli indici secondari combinati con valore-chiave e transazionalità.

Anche la reattiva comunità di lingua russa, pronta ad aiutare nella chat, ha avuto un ruolo. Lo abbiamo utilizzato attivamente e viviamo direttamente nella chat. E non dimenticare una discreta perseveranza senza errori ed errori evidenti. Se guardi la nostra storia con Tarantool, abbiamo avuto molti problemi e fallimenti con la replica, ma non abbiamo mai perso dati per colpa sua!

L'implementazione ha avuto un inizio difficile

A quel tempo, il nostro stack di sviluppo principale era .NET, al quale non esisteva alcun connettore per Tarantool. Abbiamo subito iniziato a fare qualcosa in Go. Ha funzionato bene anche con Lua. Il problema principale a quel tempo era con il debug: in .NET tutto va benissimo, ma dopo era difficile immergersi nel mondo di Lua incorporato, quando non hai debug tranne i log. Inoltre, per qualche motivo, la replica periodicamente andava in pezzi, quindi ho dovuto approfondire la struttura del motore "Tarantool". La chat ha aiutato in questo e, in misura minore, con la documentazione; a volte abbiamo guardato il codice. A quel tempo la documentazione era così così.

Quindi, nel corso di diversi mesi, sono riuscito a rimettermi in sesto e a ottenere risultati decenti lavorando con Tarantool. Abbiamo compilato gli sviluppi di riferimento in Git che hanno aiutato nella formazione di nuovi microservizi. Ad esempio, quando si è presentata un'attività: creare un altro microservizio, lo sviluppatore ha esaminato il codice sorgente della soluzione di riferimento nel repository e non è stata necessaria più di una settimana per crearne uno nuovo.

Erano tempi speciali. Convenzionalmente potresti andare dall'amministratore al tavolo successivo e chiedere: "Dammi una macchina virtuale". Circa trenta minuti dopo l'auto era già con te. Ti sei connesso, hai installato tutto e il traffico ti è stato inviato.

Oggi questo non funzionerà più: è necessario aggiungere monitoraggio e logging al servizio, coprire la funzionalità con test, ordinare una macchina virtuale o consegnarla a Kuber, ecc. In generale sarà meglio così, anche se ci vorrà più tempo e sarà più problematico.

Dividi e governa. Qual è il problema con Lua?

Si è verificato un serio dilemma: alcuni team non erano in grado di implementare in modo affidabile modifiche a un servizio con molta logica in Lua. Ciò era spesso accompagnato dal servizio non funzionante.

Cioè, gli sviluppatori stanno preparando una sorta di cambiamento. Tarantool inizia a fare la migrazione, ma la replica è ancora con il vecchio codice; Qualche DDL o qualcos'altro arriva lì tramite replica e il codice semplicemente va in pezzi perché non viene preso in considerazione. Di conseguenza, la procedura di aggiornamento per gli amministratori è stata impostata su un foglio A4: interrompi la replica, aggiorna questo, attiva la replica, disattiva qui, aggiorna lì. Incubo!

Di conseguenza, ora spesso proviamo a non fare nulla a Lua. Basta usare iproto (un protocollo binario per interagire con il server), e il gioco è fatto. Forse si tratta di una mancanza di conoscenza da parte degli sviluppatori, ma da questo punto di vista il sistema è complesso.

Non sempre seguiamo ciecamente questo copione. Oggi non abbiamo il bianco e il nero: o è tutto in Lua, oppure è tutto in Go. Sappiamo già come combinarli in modo da non ritrovarci successivamente con problemi di migrazione.

Dov'è il Tarantolo adesso?
Tarantool viene utilizzato nel servizio per il calcolo del costo finale della merce tenendo conto dei buoni sconto, noto anche come “Promoter”. Come ho detto prima, ora va in pensione: viene sostituito da un nuovo servizio di catalogo con prezzi precalcolati, ma sei mesi fa tutti i calcoli venivano fatti in Promotizer. In precedenza, metà della sua logica era scritta in Lua. Due anni fa il servizio è stato trasformato in deposito e la logica è stata riscritta in Go, perché la meccanica degli sconti era un po' cambiata e il servizio mancava di performance.

Uno dei servizi più critici è il profilo utente. Cioè, tutti gli utenti di Wildberries sono archiviati in Tarantool, e sono circa 50 milioni, un sistema suddiviso per ID utente, distribuito su più DC collegati ai servizi Go.
Secondo RPS, Promoter una volta era il leader, raggiungendo 6mila richieste. Ad un certo punto ne avevamo 50-60 copie. Ora il leader in RPS sono i profili utente, circa 12mila, questo servizio utilizza lo sharding personalizzato, diviso per intervalli di ID utente. Il servizio serve più di 20 macchine, ma sono troppe; pensiamo di ridurre le risorse stanziate, perché la capacità di 4-5 macchine è sufficiente.

Il servizio Session è il nostro primo servizio su vshard e cartuccia. Configurare vshard e aggiornare la cartuccia ha richiesto un po' di impegno da parte nostra, ma alla fine tutto ha funzionato.

Il servizio per la visualizzazione di diversi banner sul sito e nell'applicazione mobile è stato uno dei primi ad essere rilasciato direttamente su Tarantool. Questo servizio si distingue per il fatto che ha 6-7 anni, è ancora in funzione e non è mai stato riavviato. È stata utilizzata la replica master-master. Non si è mai rotto nulla.

Esiste un esempio di utilizzo di Tarantool per funzionalità di consultazione rapida in un sistema di magazzino per ricontrollare rapidamente le informazioni in alcuni casi. Abbiamo provato a utilizzare Redis per questo, ma i dati in memoria occupavano più spazio di Tarantool.

Con Tarantool funzionano anche i servizi di lista d'attesa, abbonamenti clienti, storie di moda e beni in differita. L'ultimo servizio in memoria occupa circa 120 GB. Questo è il servizio più completo dei precedenti.

conclusione

Grazie agli indici secondari combinati con valore-chiave e transazionalità, Tarantool è adatto per architetture basate su microservizi. Tuttavia, abbiamo riscontrato difficoltà durante l'implementazione di modifiche ai servizi con molta logica in Lua: i servizi spesso smettevano di funzionare. Non siamo riusciti a superare questo problema e nel tempo siamo arrivati ​​a diverse combinazioni di Lua e Go: sappiamo dove usare una lingua e dove usarne un'altra.

Cos'altro leggere sull'argomento

Fonte: habr.com

Aggiungi un commento