
Toți ne iubim poveștile. Ne place să stăm lângă foc și să vorbim despre victoriile, luptele sau experiențele noastre de muncă.
Astăzi este o astfel de zi. Și, deși poate că nu ești lângă foc, avem totuși o poveste pentru tine. O poveste despre cum am început să lucrăm cu stocarea pe Tarantool.
În vremuri de mult apuse, compania noastră avea câteva «monolite» și un «tavan» comun, la care aceste monolite se apropiau lent, dar sigur, limitând zborul companiei noastre, dezvoltarea noastră. Era o înțelegere clară: la un moment dat, ne vom lovi cu brutalitate de acest tavan.
Acum, ideologia de a împărți totul și toate, de la echipamente la logica de afaceri, ne domină. Drept urmare, avem, de exemplu, două datacentere, practic independente la nivel de rețea. Pe atunci, însă, totul era cu totul diferit.
Astăzi, pentru a face modificări, avem o mulțime de instrumente și mijloace sub formă de CI/CD, K8S etc. În vremea «monolitică», nu aveam nevoie de atâtea cuvinte străine. Era suficient să corectăm pur și simplu «stocarea» din baza de date.
Dar timpul a trecut, iar volumul de cereri a crescut odată cu el, atingând uneori RPS-uri care depășeau capacitățile noastre. Odată cu intrarea pe piața țărilor CSI, încărcarea pe procesorul Bazei de Date a primului monolit nu a scăzut sub 90%, iar RPS-urile s-au menținut la un nivel de 2400. Și nu erau doar cereri mici, ci solicitări mari cu multe verificări și JOIN-uri, care puteau accesa aproape jumătate din date, în condiții de input/output ridicat.
Când au început să apară vânzările reale de «Black Friday» — iar Wildberries a fost unul dintre primii din Rusia care le-a organizat — situația a devenit cu adevărat tristă. Asta pentru că încărcarea în astfel de zile crește de trei ori.
Ah, aceste «vreme monolitice»! Sunt sigur că și tu ai avut parte de așa ceva și încă nu poți să înțelegi cum a putut să ți se întâmple asta.
Ce să-i faci — moda este o trăsătură comună și pentru tehnologii. Acum cinci ani, a fost necesar să regândim una dintre aceste tendințe, sub forma site-ului nostru pe .NET și MS SQL Server, care păstra cu grijă toată logica operațională a site-ului. Păstra atât de mult, încât desfacerea unui astfel de monolit s-a dovedit a fi o plăcere lungă și deloc ușoară.
O mică deviere.
La diferite tipuri de evenimente spun: „dacă nu ai spart monolitul, înseamnă că nu ai crescut!” Aș dori să știu părerea ta despre aceasta, te rog să-mi scrii în comentarii.
Și a venit tunetul
Revenind la „casa noastră”. Pentru a distribui sarcina funcționalității „monolitice”, am decis să împărțim sistemul în microservicii, bazate pe tehnologii open-source. Pentru că, cel puțin, scalarea lor este mai ieftină. Și am înțeles perfect că va trebui să scalăm (și nu puțin) în proporție de 100 %. Întrucât, deja la acel moment, am reușit să intrăm pe piețele țărilor vecine, iar numărul de înregistrări, la fel ca și numărul de comenzi, a început să crească și mai mult.
Analizând primii candidați pentru a ieși din monolit în microservicii, am realizat că în 80% din cazuri, scrierea în acestea provine în 99% din sistemele back office, iar citirea — din prima linie. În primul rând, aceasta se referea la două subsisteme importante pentru noi — datele utilizatorilor și sistemul de calculare a prețului final al produselor pe baza informațiilor despre reducerile și cupoanele clienților.
Ca o notă de subsol. Acum e înspăimântător să ne imaginăm, dar pe lângă subsistemele menționate mai sus, din monolitul nostru au fost de asemenea scoase cataloagele de produse, coșul utilizatorilor, sistemul de căutare a produselor, sistemul de filtrare a cataloagelor de produse și diverse sisteme de recomandare. Pentru funcționarea fiecăruia dintre acestea, există clase separate de sisteme specializate, dar cândva toate trăiau în același „casă”.
Am planificat să scoatem datele despre clienții noștri direct dintr-un sistem shardat. Scoaterea funcționalității pentru calcularea prețului final al produselor necesita o bună scalabilitate în citire, deoarece aceasta crea cea mai mare încărcătură pe RPS și era cea mai complexă în execuție pentru bază (foarte multe date sunt implicate în procesul de calcul).
Ca urmare a acestui fapt, a apărut un schema care se potrivește bine cu Tarantool.
Atunci, pentru funcționarea microserviciilor, au fost alese scheme de lucru cu mai multe centre de date pe mașini virtuale și fizice. Așa cum este ilustrat în imagini, au fost aplicate variante de replicare Tarantool atât în modul master-master, cât și master-slave.

Arhitectură. Variante 1. Serviciul utilizatorilor
În prezent, există 24 de sharduri, fiecare având câte 2 instanțe (câte una pentru fiecare centru de date), toate în modul master-master.
Deasupra bazei de date se află aplicații care accesează replicile bazei de date. Aplicațiile interacționează cu Tarantool prin intermediul bibliotecii noastre personalizate, care implementează interfața Go-driver-ului Tarantool. Aceasta vede toate replicile și poate lucra cu masterul pentru citire și scriere. Practic, implementează modelul replica set, în care este adăugată logica de selecție a replicilor, de retry, circuit breaker și rate limit.
Există posibilitatea de a configura politica de selecție a replicii pe sharduri. De exemplu, prin round-robin.

Arhitectura. Varianta 2. Serviciul de calcul al costului final al produsului.
Cu câteva luni în urmă, cea mai mare parte a cererilor pentru calculul costului final al produselor a fost transferată către un nou serviciu, care, în principiu, funcționează fără baze de date, dar, până acum, 100% din cereri erau procesate de serviciul cu Tarantool sub capotă.
Baza de date a serviciului constă din 4 mastere, în care sincronizatorul adună datele, fiecare dintre aceste mastere împărțind datele către replicile readonly. Fiecare master are aproximativ 15 astfel de replici.
Atât în prima, cât și în a doua schemă, în cazul indisponibilității unui datacenter, aplicația poate obține date din cel de-al doilea.
Merită menționat că în Tarantool replicarea este destul de flexibilă și se poate configura în runtime. În alte sisteme au apărut dificultăți. De exemplu, modificarea parametrilor max_wal_senders și max_replication_slots în PostgreSQL necesită repornirea masterului, ceea ce în unele cazuri poate duce la întreruperea conexiunilor între aplicație și SGBD.
Caută și vei găsi!
De ce nu am făcut «ca oamenii normali» și am ales o metodă atipică? Depinde ce consideri normal. Mulți formează de fapt un cluster din Mongo și îl distribuie pe trei datacenter-uri geografic dispersate.
Atunci aveam deja două proiecte pe Redis. Primul — cache, iar al doilea reprezenta un stocare persistentă pentru date nu foarte critice. Cu acesta aveam destul de multe dificultăți, parțial din vina noastră. Uneori, volume mari stăteau în chei, iar din când în când site-ul devenea lent. Foloseam acest sistem în variantă master-slave. Și au fost multe cazuri când ceva se întâmpla cu masterul și replicarea se strica.
Adică Redis este bun pentru sarcini stateless, nu pentru stateful. În principiu, a rezolvat majoritatea sarcinilor, dar doar dacă erau soluții key-value cu câteva indecși. Însă, în acea perioadă, Redis avea probleme semnificative cu persistența și replicarea. În plus, existau plângeri legate de performanță.
Ne-am gândit la MySQL și PostgreSQL. Dar primul nu a prins la noi, iar al doilea este un produs destul de complex, așa că a construi servicii simple pe el ar fi fost nejustificat.
Am încercat RIAK, Cassandra, chiar și o bază de date grafică. Toate acestea sunt soluții destul de nișate, care nu se potriveau rolului de instrument universal pentru crearea de servicii.
În cele din urmă, ne-am oprit la Tarantool.
Ne-am adresat lui când era în versiunea 1.6. Ne-a interesat sinergia dintre key-value și funcționalitatea unei baze de date relaționale. Există indecși secundari, tranzacții și spații, ce sunt ca tabelele, dar nu sunt simple, poți stoca diferite numere de coloane în ele. Dar caracteristica ucigașă a Tarantool au fost indecșii secundari combinați cu key-value și tranzacționalitatea.
De asemenea, a avut un rol important comunitatea rusofonă reactivă, pregătită să ajute în chat. Am folosit acest lucru activ și am trăit efectiv în chat. Și nu trebuie să uităm de persistența decentă fără erori evidente și probleme. Dacă ne uităm la istoricul nostru cu Tarantool, am întâmpinat multe dureri și eșecuri cu replicarea, dar nu am pierdut niciodată date din vina lui!
Implementarea a început cu dificultăți.
La acea vreme, principalul nostru stack de dezvoltare era .NET, pentru care nu exista un conector pentru Tarantool. Am început imediat să lucrăm pe Go. Cu Lua a mers destul de bine. Principală problemă era debuggingul: în .NET era totul excelent, dar după aceea, a te cufunda în lumea Lua embedded, când nu ai altceva în afară de jurnale, era destul de complicat. În plus, replicarea se descompunea periodic, așa că a trebuit să ne aprofundăm în structura motorului Tarantool. Chatul ne-a ajutat în acest sens, documentația într-o măsură mai mică, uneori ne uitam la cod. La acea vreme, documentația era destul de slabă.
Așa, în decursul câtorva luni, am reușit să acumulez experiență și să obțin rezultate notabile în lucrul cu Tarantool. Am documentat în git soluțiile de referință, care au fost utile pentru dezvoltarea noilor microservicii. De exemplu, când apărea sarcina de a crea un nou microserviciu, dezvoltatorul consulta codul sursă al soluției de referință din depozit, iar crearea unui nou microserviciu nu dura mai mult de o săptămână.
A fost o perioadă specială. În esență, atunci puteai să te apropii de administratorul de la biroul vecin și să ceri: „Dă-mi o mașină virtuală”. Peste aproximativ treizeci de minute, mașina era deja la tine. Te conectai singur, instalai totul și începeau să-ți direcționeze trafic pe ea.
Astăzi, lucrurile nu mai stau așa: trebuie să configurezi monitorizarea pe serviciu, să implementezi jurnalizare, să acoperi funcționalitatea cu teste, să comanzi o mașină virtuală sau să o implementezi în Kuberen și așa mai departe. În general, așa va fi mai bine, deși mai îndelungat și complicat.
Împărțiți și stăpâniți. Cum stau lucrurile cu Lua?
A fost o dilemă serioasă: unele echipe nu reușeau să implementeze modificări în serviciu cu un grad mare de logică scrisă în Lua. De multe ori, acest lucru se însoțea de nefuncționalitatea serviciului.
Adică, dezvoltatorii pregătesc o anumită modificare. Tarantool începe să facă migrarea, iar replica încă folosește codul vechi; acolo primește, prin replicare, un DDL sau altceva, iar codul pur și simplu se destramă, pentru că nu a fost luat în considerare. Ca urmare, procedura de actualizare a administratorilor era scrisă pe o foaie A4: oprește replicarea, actualizează asta, activează replicarea, oprește aici, actualizează acolo. Coșmar!
În consecință, acum încercăm de cele mai multe ori să nu facem nimic în Lua. Pur și simplu folosim iproto (protocol binar pentru interacțiunea cu serverul) și cam atât. Poate că acest lucru se datorează lipsei de cunoștințe a dezvoltatorilor, dar din această perspectivă, sistemul este complex.
Nu urmăm întotdeauna orbește acest scenariu. Astăzi, nu mai avem alb și negru: fie totul este în Lua, fie totul este în Go. Începem să înțelegem cum să le combinăm, astfel încât ulterior să nu ne confruntăm cu probleme de migrare.
Unde se află acum Tarantool?
Tarantool este utilizat în serviciul de calcul al prețului final al produselor, inclusiv cupoanele de reducere, cunoscut sub numele de „Promotayzer”. Așa cum am menționat anterior, acum acesta se retrage: este înlocuit de un nou serviciu de catalog cu prețuri pre-calculate, dar cu șase luni în urmă toate calculele erau efectuate în „Promotayzer”. O jumătate din logica sa a fost scrisă în Lua. Acum doi ani, serviciul a fost transformat într-un depozit, iar logica a fost rescrisă în Go, deoarece mecanica reducerilor s-a schimbat puțin și serviciul nu avea suficientă performanță.
Unul dintre cele mai critice servicii este profilul utilizatorului. Asta înseamnă că toți utilizatorii Wildberries sunt stocați în Tarantool, iar numărul acestora se ridică la aproximativ 50 de milioane. Sistemul este shardat în funcție de ID-ul utilizatorului, distribuit pe mai multe centre de date, cu legături pe servicii Go.
La RPS, liderul a fost odată „Promotayzer”, atingând până la 6 mii de cereri. La un moment dat aveam 50-60 de instanțe. Acum, liderul în RPS este profilul utilizatorului, având aproximativ 12 mii. În acest serviciu se aplică un shardare personalizată cu divizarea pe intervale de ID-uri de utilizator. Serviciul deserveste mai mult de 20 de mașini, dar asta este prea mult; plănuim să reducem resursele alocate, deoarece patru-patru mașini sunt suficiente.
Serviciul de sesiuni este primul nostru serviciu pe vshard și Cartridge. Configurarea vshard și actualizarea Cartridge au necesitat un anumit efort din partea noastră, dar în final totul a mers bine.
Serviciul de afișare a diferitelor bannere pe site și în aplicația mobilă a fost unul dintre primele lansate direct pe Tarantool. Acest serviciu este remarcabil deoarece are aproximativ 6-7 ani, este încă funcțional și nu a fost niciodată repornit. A fost utilizată replicarea master-master. Niciodată nu s-a defectat nimic.
Există un exemplu de utilizare a Tarantool pentru funcționalitatea de bucle rapide în sistemul de depozit pentru a verifica rapid informațiile în anumite cazuri. Am încercat să folosim Redis pentru acest lucru, dar datele în memorie ocupau mai mult spațiu decât în Tarantool.
Serviciile de listă de așteptare, subscripțiile clienților, poveștile la modă și produsele amânate funcționează de asemenea cu Tarantool. Ultimul serviciu ocupă aproximativ 120 GB în memorie. Este cel mai voluminos serviciu din cele menționate anterior.
Concluzie
Datorită indexurilor secundare combinate cu key-value și tranzacționalitate, Tarantool este ideal pentru arhitecturi bazate pe microservicii. Totuși, ne-am confruntat cu dificultăți atunci când implementam modificări în servicii cu multă logică scrisă în Lua — serviciile adesea nu mai funcționau. Nu am reușit să învingem acest lucru, iar în timp am ajuns la combinații diferite de Lua și Go: știm unde să folosim un limbaj și unde pe celălalt.
What else to read on the topic
- Construim de la zero o aplicație de înaltă capacitate pe Tarantool
- O alegere de încredere — liderul în Tarantool Cartridge
- Canalul Telegram Tarantool cu știri despre produs
- Discută despre Tarantool în chatul comunității
Sursa: habr.com
