Scalarea rapidă a stocării online pentru peste 1 miliard de utilizatori ChatGPT (Partea a II-a)
Cum am optimizat Azure Cosmos DB în Habitat, platforma noastră de stocare pentru aplicații, pentru a gestiona o creștere fără precedent.
Toate produsele OpenAI necesită acces rapid și fiabil la date, asigurat de platforma noastră de stocare, Habitat. Aceasta trebuie să răspundă în milisecunde pentru peste 1 miliard de utilizatori din 40 de regiuni geografice. Infrastructura noastră s-a confruntat cu o provocare extraordinară: să susțină o creștere explozivă și cazuri de utilizare noi, îmbunătățind în același timp fiabilitatea, performanța și ritmul de lucru al dezvoltatorilor de produse. Pentru a răspunde acestei provocări, a trebuit să regândim proiectarea și operarea platformei noastre de stocare online. Am evaluat constant compromisurile, urmând aceeași ordine: mai întâi, suficientă fiabilitate pentru traficul critic al produselor; apoi, suficientă viteză pentru utilizatorii din întreaga lume; în cele din urmă, operare eficientă la scară masivă.
Această serie în două părți explică modul în care am transformat Habitat dintr-o simplă bibliotecă client și o bază de date într-o platformă de stocare distribuită global, care deservește peste 500 de petabyți de date. Partea I a urmărit evoluția Habitat de la un client Python la un serviciu. A prezentat și tehnicile care ne-au permis să ducem un serviciu bazat pe Python mult dincolo de ceea ce mulți ar considera fezabil.
În acest articol, Partea a II-a, explicăm cum am scalat componenta de stocare subiacentă: Azure Cosmos DB. Printr-o colaborare strânsă cu echipa Azure, am ajuns la o abordare multi-tenant viabilă, cu containere administrate în comun și performanțe excelente la citire, la scară globală masivă.
Figura 01 · Ce este Habitat?
Platformă de stocare online
Habitat este platforma de stocare online pe care am construit-o pentru ca produsele OpenAI să poată accesa rapid și fiabil informațiile necesare.
- Solicitare
- Răspuns
- Modificări (CDC)
Pe măsură ce companiile cresc, echipele de infrastructură trec adesea de la operarea unor sisteme cu un singur tenant la sisteme multi-tenant. În arhitectura cu un singur tenant, fiecare echipă responsabilă de o zonă a produsului își întreține propriul sistem. Astfel, impactul incidentelor este limitat, responsabilitățile sunt ușor de delimitat, iar sarcinile de lucru sunt izolate. Pe măsură ce echipele și zonele de produs se extind, această abordare devine costisitoare. Arhitectura cu un singur tenant face fiecare echipă de produs responsabilă de planificarea capacității și duce adesea la alocarea unor resurse mult peste necesar.
În schimb, arhitectura multi-tenant atribuie controlul unei echipe centralizate de administrare a bazelor de date, care dispune de cunoștințe și experiență mai solide în alocarea resurselor. Totuși, această arhitectură generează propriile probleme, precum cele cauzate de consumatorii abuzivi de resurse partajate, când un tenant consumă o proporție neobișnuit de mare din resurse, în detrimentul celorlalți tenanți.
În Habitat, a trebuit să cântărim toate aceste compromisuri pentru a proiecta un sistem de stocare fiabil și eficient la scară mare. Astăzi, Habitat este un strat de baze de date multi-tenant pentru multe produse OpenAI. Însă am parcurs un traseu circular: de la un singur container Azure Cosmos DB multi-tenant, la containere de stocare single-tenant, apoi înapoi la un container multi-tenant folosit implicit. Suntem încă la început cu arhitectura multi-tenant în Habitat. Susținem numeroase cazuri de utilizare, dar am putut amâna investițiile în această zonă folosind, ori de câte ori a fost posibil, mecanismele de bază integrate în Azure Cosmos DB.
Înainte de a descrie parcursul nostru cu Azure Cosmos DB, iată câteva noțiuni de bază:
Un cont Azure Cosmos DB definește un set de containere și o politică de replicare
Fiecărui container i se alocă un anumit randament, exprimat în unități de cerere pe secundă (RU/s)
Datele din fiecare container sunt stocate prin fragmentare după o cheie de partiție logică specificată, cu limite documentate de stocare și randament pentru fiecare cheie de partiție logică
Azure Cosmos DB distribuie cheile de partiție logică între un număr mai mic de partiții fizice subiacente. Acestea se divid în mai multe partiții fizice când volumul stocat depășește un prag sau când containerul are nevoie de mai multe partiții fizice pentru a susține randamentul alocat
Inițial, acceptam orice încărcare de la clienți, bazându-ne pe limita declarată de 10 mii RU/s per cheie de partiție logică pentru a exercita contrapresiune. Tot la început, foloseam un singur container Azure Cosmos DB implicit în fiecare cont. Abordarea a funcționat destul de bine, dar s-a dovedit problematică din câteva motive:
Din cauza unor decizii inițiale privind API-ul, am expus direct clienților selecția cheii de partiție logică. Ca urmare, apar frecvent coliziuni pe chei de partiție uzuale, precum user_id sau workspace_id, între diverse cazuri de utilizare ale produselor. Întrucât aceste cazuri de utilizare împărțeau limitele Azure Cosmos DB pentru aceleași chei de partiție logică, arhitectura restrângea randamentul total disponibil unui utilizator.
Înainte de trecerea la Habitat și Azure Cosmos DB, o problemă frecventă la scalarea Postgres era că numeroasele cereri ale unei organizații sau chei intens solicitate — un tenant care genera o încărcare disproporționat de mare — puteau bloca întreaga bază de date. Am depus un efort colectiv considerabil pentru a memora acele chei în cache și a integra mecanisme de rezervare temporară la ratările de cache, astfel încât încărcarea rezultată să nu suprasolicite baza de date subiacentă.
Figure 02a · Logical partition key limits
Different clients, the same partition key
Deși limitele documentate pentru volumul datelor și randament se aplică cheilor de partiție logică, ele sunt impuse, de fapt, la nivelul partiției fizice. În practică, aceasta înseamnă că partițiile logice nu pot atinge 10.000 RU/s. În schimb, ele împart limitele partiției fizice cu toate celelalte chei de partiție logică aflate pe aceeași partiție fizică.
Acest lucru a permis ca sarcinile de lucru care consumau excesiv resursele partajate să afecteze numeroase chei de partiție logică fără legătură între ele, sarcinile de lucru care operau asupra datelor aferente unor funcționalități de nișă ale produsului perturbând procesele esențiale de autentificare și înregistrare.
Figure 02b · Noisy neighbors
Different users, the same physical partition
Limita de randament a unei partiții fizice este și ea variabilă, în funcție de randamentul total alocat containerului Azure Cosmos DB. Randamentul alocat containerului este distribuit aproximativ uniform între partițiile fizice ale acestuia.
Pe măsură ce volumul datelor crește, partițiile fizice se divid. Numărul total de partiții crește, dar randamentul total alocat rămâne neschimbat. Prin urmare, limita efectivă de randament per partiție scade pe măsură ce volumul datelor crește.
Pentru cazurile noastre de utilizare de tip blob, cu cele mai mari cerințe de stocare, apare astfel un mod de defectare în care simpla creștere a datelor stocate reduce randamentul disponibil sarcinilor active, chiar dacă ratele cererilor și utilizarea rămân stabile.
Figure 02C · Weak partitions
The limit falls below demand
A partition splits when it reaches its storage limit. Each child receives half the throughput capacity.
Containerele separate contribuie la rezolvarea parțială a acestor limitări privind cheile de partiție și a problemelor cauzate de consumatorii abuzivi de resurse partajate. Prin utilizarea unor containere separate, fiecăruia i se pot aloca propriile partiții fizice independente, astfel încât doar sarcinile de lucru diferite din cadrul aceluiași container pot concura excesiv pentru resurse sau se pot suprapune în spațiul cheilor de partiție. Dezavantajul este că aprovizionarea cu containere noi implică un anumit efort suplimentar, deoarece fiecare container necesită o planificare individuală a capacității. Prin urmare, dorim să creăm containere doar atunci când delimitarea dintre servicii sau cazuri de utilizare justifică acest lucru.
Am început să folosim containere Azure Cosmos DB separate pentru cele mai critice cazuri de utilizare noi care necesitau o izolare strictă. Împreună cu un script care gestiona partițiile cu capacitate redusă, sincronizând randamentul total alocat fiecărui container cu numărul său de partiții fizice, această abordare ne-a permis să evităm în mare parte toate problemele întâmpinate.
Totuși, întrucât pornisem de la un container implicit, multe cazuri de utilizare critice mai vechi au rămas, din păcate, blocate acolo în lipsa migrării datelor. Pentru a proteja serviciile critice care încă depindeau de datele din containerul implicit partajat, sfătuiam adesea echipele să creeze containere separate pentru servicii noi sau funcționalități majore. Pe măsură ce ne extindeam, presiunea asupra containerului implicit creștea, la fel și numărul incidentelor din producție. Am început să alocăm containere pentru orice serviciu nou sau funcționalitate majoră, doar pentru a proteja containerul implicit de o încărcare suplimentară.
Astfel, am evitat multe întreruperi la nivelul întregului site, limitând impactul la degradarea unor funcționalități sau servicii. Însă, în cele din urmă, efortul suplimentar de alocare a containerelor noi și-a făcut simțite efectele:
În vechiul container implicit partajat, era puțin probabil ca un caz de utilizare nou care trecea de la 0 QPS la 1 milion QPS să modifice semnificativ utilizarea totală agregată. Într-un container izolat, însă, trecerea unui caz de utilizare nou de la 0 la 1 milion QPS putea însemna o încărcare de 1.000 de ori mai mare decât nivelul de bază generat doar de testarea internă a produsului.
Cu containere dedicate, echipele trebuiau acum să nu uite să aloce din timp randamentul estimat pentru lansare. Echipele de produs lansau adesea funcționalități în producție și uitau să mărească în prealabil capacitatea. Ajungeam astfel să petrecem ziua lansării în ședințe de gestionare a incidentelor grave, încercând să scalăm containerele în ultimul moment.
Acesta este un avantaj esențial al combinării sarcinilor de lucru în sisteme multi-tenant, la care renunțăm în favoarea unei izolări mai bune prin această strategie cu containere.
Figure 03 · Lack of stable aggregate growth
The same workload, different headroom
1K RU/s during load testing → 1M RU/s at launch
În timp, monitorizarea utilizării containerelor dedicate a ajuns să necesite și o cunoaștere aprofundată a produsului, pentru a anticipa schimbările sau creșterile de trafic.
Putem oferi un script simplu pentru planul de control, care să mărească randamentul alocat fiecărui container pe baza tendințelor de creștere. Însă, fără o creștere agregată stabilă, scalarea corectă a acestora a ajuns să implice practic fiecare echipă de produs de la OpenAI în planificarea capacității.
Această abordare nu a funcționat odată cu extinderea organizației: atenția acordată alocării resurselor Azure Cosmos DB varia mult de la o echipă responsabilă de un serviciu la alta.
Pe măsură ce organizația creștea, aceste probleme operaționale deveneau tot mai greu de gestionat. În lipsa unei singure echipe centrale responsabile de planificare, multe echipe planificau deficitar. Prin urmare, am revenit treptat la o soluție multi-tenant și am lucrat îndeaproape cu echipa Azure pentru a remedia problemele inițiale printr-o arhitectură cu resurse partajate între tenanți:
Limitarea prioritară a debitului pentru cheile cu cel mai intens trafic împiedică consumatorii abuzivi de resurse partajate să utilizeze întreaga capacitate de procesare disponibilă pentru o anumită partiție fizică. Acest lucru reduce efectul provocat de acești consumatori, prin care o singură cheie cu trafic intens poate afecta întregul site.
În mod similar, QoS bazat pe clasificarea cererilor împiedică sarcinile offline, precum inserările în masă sau extragerile de date, să utilizeze întregul randament al unei partiții fizice. Atribuind acestor cereri o prioritate mai mică, ele sunt limitate primele. Astfel, evităm limitarea cererilor interactive cu prioritate mai mare, care deservesc utilizatorii finali.
Azure Cosmos DB avea deja un mod fără server care ar fi rezolvat problema partițiilor cu capacitate redusă întâlnită în modul cu resurse alocate. Exista însă un dezavantaj major: scalarea se baza doar pe volumul de stocare utilizat, iar utilizarea RU era limitată la 5 mii RU/s per partiție fizică. Aceasta ar fi rezolvat problema partițiilor cu capacitate redusă, dar ne-ar fi împiedicat să scalăm cazurile de utilizare cu consum mare de RU.
Echipa Azure Cosmos DB a creat pentru noi un mod fără server îmbunătățit, care permitea fiecărei partiții fizice să ajungă la 10 mii RU/s și introducea divizarea bazată pe utilizarea RU, pe lângă cea bazată pe volumul stocat. Astfel, nu a mai fost nevoie să monitorizăm și să scalăm manual containerele.
Datorită acestor modificări, am putut reveni la utilizarea unui singur container partajat, ceea ce a redus semnificativ necesitatea planificării inițiale sau continue a capacității de către echipele de dezvoltare a produselor, menținând totodată izolarea între sarcinile de lucru. În lunile care au urmat, nu am mai înregistrat niciun incident legat de alocarea resurselor sau de consumatorii abuzivi de resurse partajate, în ciuda accelerării dezvoltării produselor.
Când companiile ajung la dimensiunea OpenAI, serviciile administrate devin mai puțin „administrate”. Multe sarcini de lucru devin cazuri atipice în infrastructura furnizorului cloud. Pe măsură ce OpenAI a devenit unul dintre cei mai mari utilizatori Azure Cosmos DB, operarea cu succes a acestuia a necesitat un alt model de lucru: teste comune, tablouri de bord comune, canale directe între ingineri și responsabilitate comună pentru modurile de defectare care apar doar la scara noastră. Astăzi, cel mai mare cont Azure Cosmos DB al nostru stochează zeci de petabyți de date și deservește peste 20 de milioane QPS. Din câte știm, suntem singura companie care a implementat Azure Cosmos DB la această scară.
La sfârșitul anului 2024, o întrerupere regională a arătat clar de ce era necesară această colaborare. Atunci, o pană de curent a afectat regiunea Azure principală a unuia dintre cele mai mari conturi Azure Cosmos DB ale noastre. În timpul comutării de avarie, am realizat că mutarea celor mai mari conturi într-o regiune secundară ar dura câteva ore. Nici echipa noastră, nici echipa Azure Cosmos DB nu testaseră această operație la scara noastră.
Circa o lună mai târziu, când am readus acele conturi în regiunea inițială, am declanșat o altă întrerupere gravă. Un val masiv de conexiuni către regiunea inițială a suprasolicitat gateway-ul Azure Cosmos DB al acesteia. O particularitate a modului în care clientul Azure Cosmos DB în modul gateway gestiona comutările de avarie a făcut ca toți clienții să stabilească imediat conexiuni și să trimită cereri către regiunea inițială, deși numai o parte dintre partițiile fizice reveniseră acolo.
La fiecare întrerupere, atât OpenAI, cât și Azure și-au urmat procesele de gestionare a incidentelor, identificând mai multe cauze de bază și implementând remedieri. Dar aceste întreruperi erau simptomele unei probleme sistemice mai ample, legate de modul în care echipa noastră și echipa Azure Cosmos DB operau și testau sistemele. La început, serviciile administrate ne-au permis să avansăm rapid și să ne concentrăm pe obiectivele de afaceri. La scară mare, serviciile administrate devin mai puțin administrate și necesită o integrare strânsă cu furnizorul la toate nivelurile, de la proiectare la operare.
Astăzi, echipele de inginerie Habitat și Azure monitorizează împreună fiecare nivel al Habitat, de la straturile noastre de servicii până la straturile de stocare fizică Azure Cosmos DB. Operăm și testăm schimbările pe un cont Azure Cosmos DB de dimensiunea celui de producție, dar separat de producție. Testăm și îmbunătățim împreună SDK-urile și stabilim bune practici pentru scalarea și dimensionarea conturilor noastre Azure Cosmos DB. Inginerii pot comunica direct între ei prin Teams și am creat chiar modalități de alertare directă reciprocă, fără a trece prin nivelurile de asistență.
În ultimul an, s-au depus eforturi comune considerabile pentru a îmbunătăți scalabilitatea planului de control și a gateway-ului Azure Cosmos DB, prin adăugarea unor mecanisme de protecție împotriva supraîncărcării și de stocare în cache a diverselor metadate Azure Cosmos DB la nivelul gateway-ului, pentru a proteja partiția de metadate Azure Cosmos DB, reducerea presiunii generate de ansamblul nostru de procese Python habitat-service prin gruparea conexiunilor și reutilizarea mai frecventă a acestora, colocarea sarcinilor de lucru acolo unde este posibil și izolarea sarcinilor de lucru critice de cele care se execută offline, prin utilizarea unor VPC-uri diferite.
Acest nivel de colaborare inginerească a fost esențial pentru stabilitatea Azure Cosmos DB în ultimul an. Orice sistem suficient de mare sau de important necesită o astfel de muncă în echipă: depășirea delimitărilor rigide de responsabilitate și colaborarea dincolo de granițele organizaționale.
După cum am menționat în Partea I, filosofia noastră de bază este: întâi să funcționeze, apoi să fie rapid, apoi să coste puțin. Mai întâi fiabilitatea, apoi performanța, apoi eficiența. Habitat devenise o infrastructură critică pentru OpenAI, așa că prima prioritate a fost să-i asigurăm fiabilitatea. Pe măsură ce sistemul s-a stabilizat în 2025, iar OpenAI s-a extins la nivel global, latența a devenit următoarea constrângere pentru utilizatori și echipele de produs.
Resursele de calcul și de stocare se aflau adesea în regiuni diferite, ceea ce făcea inevitabile cererile între regiuni.
Figure 04 · Improving performance at a global scale
Global traffic
Compute and storage capacity were often located in different regions, making cross-region requests unavoidable.
Amplasările geografice ale resurselor de calcul și stocare sunt prezentate doar cu titlu ilustrativ.
Latența varia mult în funcție de locul unde erau stocate datele și de cel unde era procesată cererea. Pentru a îmbunătăți performanța cererilor Habitat, dezvoltatorii de produse recurgeau la cache suplimentar pe partea de client, gruparea cererilor, reducerea citirilor și scrierilor în baza de date și scoaterea operațiilor de pe calea critică ori de câte ori era posibil. Deși au rezultat unele soluții de proiectare interesante, mai reziliente la problemele bazei de date, produsele au devenit și mai complexe, iar iterațiile de dezvoltare au încetinit. Astfel, nu ne-am atins obiectivul Habitat: dezvoltarea rapidă a produselor, fără a fi nevoie de înțelegerea bazei de date.
Aceasta a fost o prioritate majoră pentru noi în 2026. Am dezvoltat o strategie pe mai multe niveluri pentru optimizarea citirilor, care reprezintă peste 90% din cererile Habitat:
Avem mai multe conturi Azure Cosmos DB în diverse regiuni Azure din lume, pentru utilizatorii cu cerințe privind rezidența datelor. Chiar și pentru utilizatorii fără cerințe stricte privind rezidența datelor, plasarea datelor în apropierea lor îmbunătățește experiența prin reducerea latenței.
În practică, nu putem aplica pe scară largă această abordare în afara cazurilor care impun rezidența datelor, deoarece amplasarea este limitată de capacitatea fizică a infrastructurii cloud. Din cauza dimensiunii seturilor noastre de date, multe regiuni nu pot găzdui volumul enorm de stocare necesar pentru partea de trafic care le revine proporțional.
În regiunile cu capacitate limitată a centrelor de date, a alimentării electrice sau a răcirii, uneori trebuie să alegem direct: rezervăm capacitate pentru stocare colocată și latență Habitat mai mică sau folosim acea capacitate pentru resurse suplimentare de calcul și rutăm cererile de stocare mai departe.
Prin urmare, deciziile de amplasare sunt adesea un compromis de produs între: A) optimizarea latenței pentru diverse produse și grupuri de utilizatori și B) capacitatea brută de stocare și calcul.
Pentru sarcinile de lucru unde latența este critică, precum metadatele de autentificare necesare la fiecare cerere, reducem timpul dus-întors (RTT) între resursele de calcul și Habitat folosind conturi Azure Cosmos DB cu replicare extinsă în numeroase regiuni secundare. Unele conturi se replică în toate cele 40 de regiuni Azure unde procesăm trafic; altele, în cel puțin o regiune de pe fiecare continent.
A trebuit să integrăm în Habitat, mai devreme decât ne-am fi dorit, un strat transparent de mutare și rutare a datelor, pentru a putea muta seturi de date între conturi cu topologii de replicare diferite.
Totuși, și această abordare este, în cele din urmă, limitată de capacitate și, prin urmare, se aplică doar câtorva seturi de date atent selectate.
Sarcinile Habitat sunt dominate de citiri: aplicațiile preiau constant setări, stări și alte proprietăți. O parte disproporționat de mare a traficului provine dintr-un set de lucru relativ mic, cu tipuri de date accesate frecvent. De aceea, sistemul se pretează foarte bine la memorarea în cache distribuit. Deși cache-ul îmbunătățește performanța infrastructurii dintr-o singură regiune, beneficiile se amplifică într-un sistem multiregional, unde poate „ascunde” latența dintre regiuni.
Am integrat în Habitat un nivel distribuit de stocare în cache auxiliară. Acesta păstrează o copie a obiectelor și muchiilor accesate recent pe servere Valkey din infrastructura noastră, aproape de locul unde sunt procesate cererile utilizatorilor. De regulă, astfel de cache-uri folosesc un TTL care echilibrează rata de găsire în cache și gradul de învechire a datelor. Un TTL scurt reduce învechirea datelor, dar limitează beneficiile cache-ului: elementele expiră repede și trebuie preluate mai des. Un TTL mai lung crește rata de găsire în cache, dar furnizează date învechite mai mult timp, afectând experiența utilizatorilor și făcând comportamentul produsului imprevizibil.
O altă abordare este invalidarea explicită atunci când aplicația efectuează operații de scriere asupra acelorași date subiacente. Aceasta îmbunătățește radical actualitatea datelor din cache, dar poate fi greu de implementat corect. Rămâne totodată vulnerabilă la cazuri-limită, precum erorile parțiale, care lasă date învechite în cache. Implementările multiregionale agravează aceste probleme: rețelele dintre regiuni sunt mai puțin fiabile, iar operațiile cache intră în concurență cu replicarea stocării subiacente. Adăugarea unui TTL limitează vechimea maximă a datelor, dar păstrează compromisul inerent TTL-ului descris mai sus.
Am adoptat o abordare mai avansată a invalidării, urmând exemplul unor sisteme precum TAO de la Meta. Cache-ul integrat Habitat folosește capturarea modificărilor datelor (CDC) prin fluxul de modificări Azure Cosmos DB pentru a propaga invalidările global în câteva secunde. Astfel, obține rate mari de găsire în cache, menținând datele aproape la zi. Un serviciu din infrastructura noastră consumă acest flux și invalidează cache-urile locale când datele subiacente sunt actualizate. La următoarea citire, datele nu mai sunt găsite în cache, iar acesta este populat cu cea mai recentă versiune.
Am redus semnificativ latența și prin eliminarea procesării suplimentare din serviciul Habitat, rescriind codul în Rust, mai performant decât implementarea inițială în Python.
Împreună, aceste schimbări au redus latența p50 globală la citire de la circa 120 ms la circa 10 ms: o îmbunătățire de 12 ori de când am început să ne concentrăm pe performanță, la începutul acestui an.
Figure 05 · Improving performance at a global scale
p50 latency for reads
Three major design changes improved read latency
Deși cache-ul a redus radical latența mediană, cele mai lente cereri necesită încă preluarea datelor absente din cache din stocarea subiacentă, adesea din regiuni îndepărtate. Pe măsură ce adăugăm capacitate și îmbunătățim eficiența stocării, vrem să abordăm o provocare mai profundă: plasarea datelor, de la început, mai aproape de locul de unde vor fi accesate.
Un sistem CDC fiabil și scalabil, care propagă modificările bazei de date către sistemele din aval, este esențial nu doar pentru strategia de cache Habitat. Milioane de modificări capturate pe secundă, din mii de containere și milioane de partiții, trec prin peste o sută de subiecte Kafka. Ele alimentează și indecși secundari cu consistență eventuală, fluxuri de mutare a datelor, analize offline și alte funcționalități de produs în timp real. Pe măsură ce infrastructura subiacentă s-a extins global, detectarea modificărilor rândurilor a devenit tot mai complexă. Dacă un client vrea să înregistreze o funcție callback executată la fiecare modificare a rândurilor de tipul său, trebuie mai întâi să identifice conturile și containerele Cosmos care îi conțin datele și implementarea serviciului CDC care urmărește acele containere în regiunile respective. De asemenea, trebuie să scaleze corect ansamblul proceselor de lucru CDC, Kafka și propriul consumator. Platforma noastră CDC urmărește să ascundă această complexitate de dezvoltatorii de produse și să ofere o interfață simplă: clienții înregistrează funcția care trebuie apelată pentru rândurile modificate, iar noi gestionăm infrastructura și scalarea.
Un plan de control intern asigură continuu capturarea modificărilor din toate containerele necesare, selectează regiunile Cosmos din care se citește și distribuie eficient sarcinile între mii de procese de lucru din mai multe regiuni geografice. Folosirea regiunilor replică și a citirilor de flux cu prioritate redusă protejează traficul Habitat sensibil la latență de sarcinile de capturare din fundal. Într-un ansamblu atât de mare apar permanent căderi ale proceselor de lucru, probleme cu containerele, erori în depozitul rezervărilor temporare, configurații invalide și defecțiuni la destinație. Am consolidat gestionarea ciclului de viață al proceselor CDC și a rezervărilor temporare, am izolat defecțiunile între fluxuri și am creat protecții pentru schimbările de configurație și implementările treptate. Folosim cozi pentru mesaje nelivrate, astfel încât erorile permanente de livrare să nu blocheze procesarea mesajelor următoare. Tolerăm întreruperile regionale comutând procesele de citire către alte regiuni Cosmos. La scara noastră, a trebuit chiar să modificăm SDK-ul CDC Azure pentru a eficientiza punctele de control: le grupăm în memorie și le persistăm doar periodic.
Deși modul în care Habitat folosește intern Azure Cosmos DB este complex, valoarea sa a constat mereu în ascunderea detaliilor de infrastructură față de dezvoltatori, pentru a accelera dezvoltarea produselor. Platforma noastră CDC urmează același principiu.
O echipă mică a reușit să susțină o platformă de stocare în creștere rapidă menținând intenționat un API de stocare restrâns, continuând scalarea serviciului Python și prioritizând cele mai urgente provocări inginerești. Ne-am concentrat mai întâi pe fiabilitatea traficului critic al produselor, apoi pe performanța citirilor pentru utilizatorii globali și, în final, pe eficiența operațională la scară mare. Această abordare a permis creșterea rapidă și noi cazuri de utilizare, îmbunătățind totodată fiabilitatea, performanța și ritmul dezvoltării produselor.
Pentru a scala Habitat și stocarea conversațiilor pentru următorul miliard de utilizatori, trebuie să rezolvăm dificultatea replicării datelor în întreaga infrastructură, la o scară și mai mare. Pentru a anticipa această nevoie, dezvoltăm intern un sistem propriu de stocare online la scară de exabyți, optimizat pentru tipurile voluminoase de date Habitat. Acest sistem, aflat în dezvoltare, combină nucleul RocksDB Cloud de la Rockset cu replicarea bazată pe Raft. El implementează același model de documente ca Azure Cosmos DB, dar folosește stocare dezagregată și replicare fizică pentru a reduce capacitatea flash necesară, în schimbul unui vârf QPS mai mic.
Dacă te interesează să lucrezi la astfel de proiecte de infrastructură de date, la scara sistemelor de vârf, vezi posturile disponibile.


