OpenAI

23. oktobar 2026.

Inženjering

Brzo skaliranje online pohrane za više od milijardu korisnika ChatGPT‑a (II dio)

Kako smo optimizirali Azure Cosmos DB u Habitatu, našoj platformi za pohranu aplikacijskih podataka, da bismo podržali rast bez presedana.

Autori: Jon Lee, Hrachya Hakobyan i Chaomin Yu, članovi tehničkog tima

Učitavanje…

Svi proizvodi kompanije OpenAI zahtijevaju brz i pouzdan pristup podacima, koji osigurava naša platforma za pohranu Habitat. Ona mora odgovarati u milisekundama na zahtjeve više od milijardu korisnika u 40 geografskih regija. Naša infrastruktura suočila se s izuzetnim izazovom: podržati eksplozivan rast i nove slučajeve upotrebe, a istovremeno nastaviti poboljšavati pouzdanost, performanse i brzinu rada razvojnih timova. Da bismo riješili taj izazov, morali smo preispitati dizajn naše platforme za online pohranu i način na koji njome upravljamo. Stalno smo procjenjivali kompromise, vodeći se ovim redoslijedom: prvo postići dovoljnu pouzdanost za kritični saobraćaj proizvoda, zatim dovoljnu brzinu za korisnike širom svijeta i, na kraju, učinkovito upravljati sistemom ogromnih razmjera.

Ovaj serijal u dva dijela objašnjava kako smo Habitat razvili od jednostavne klijentske biblioteke i baze podataka do globalno distribuirane platforme za pohranu koja omogućava pristup više od 500 petabajta podataka. Prvi dio bavio se razvojem Habitata od Python klijenta do servisa. Obuhvatio je i tehnike koje su nam omogućile da servis zasnovan na Pythonu proširimo daleko izvan onoga što bi mnogi smatrali praktičnim.

U ovom, drugom dijelu objašnjavamo kako smo skalirali osnovnu komponentu za pohranu: Azure Cosmos DB. Bliskom saradnjom s timom za Azure došli smo do održivog višekorisničkog pristupa sa zajednički upravljanim kontejnerima, uz odlične performanse čitanja u ogromnim, globalnim razmjerama.

Slika 01 · Šta je Habitat?

Platforma za mrežnu pohranu

Habitat je platforma za mrežnu pohranu koju smo izgradili kako bi OpenAI proizvodi brzo i pouzdano pristupali potrebnim informacijama.

  • Zahtjev
  • Odgovor
  • Promjene (CDC)

Klijenti

Platforma za mrežnu pohranu

Resursi pohrane

  • ChatGPT
  • API
  • Codex
  • Interne usluge
  • I još mnogo toga

Habitat

  • PredmemoriranjePredmemorije
  • ACL pravilaAutorizacija
  • Smještaj i rezidentnost podatakaRezidentnost podataka
  • ŠifriranjeSigurnost podataka
  • IzolacijaVišekorisnički rad
  • Ograničavanje stopeOblikovanje zahtjeva
  • UsmjeravanjePronalaženje šeme · Rezidentnost podataka
  • Azure Cosmos DBMrežna pohrana
  • NanobaseMrežna pohrana
  • ValkeyPredmemorije
  • Pohrana blobovaResursi pohrane
CDC uslugeEvidentiranje promjena podataka
  • Databricks
  • Rockset
  • Kafka
  • I još mnogo toga

Pouzdan višekorisnički sistem velikih razmjera

Kako kompanije rastu, infrastrukturni timovi često prelaze s jednokorisničkih na višekorisničke sisteme. Jednokorisnički pristup, u kojem svaki tim zadužen za dio proizvoda održava vlastiti sistem, ograničava domet kvarova, jasno razdvaja odgovornosti i osigurava izolaciju radnih opterećenja. Kako timovi i proizvodi rastu, održavanje takvog pristupa postaje skupo. U jednokorisničkom pristupu svaki tim za razvoj proizvoda odgovoran je za planiranje kapaciteta, što često dovodi do dodjele znatno više resursa nego što je potrebno.

Nasuprot tome, višekorisnički pristup prepušta kontrolu centralnom timu za baze podataka, koji ima više znanja i iskustva u dodjeli resursa. Ali višekorisnički pristup stvara vlastite probleme, poput bučnih susjeda, kada jedan korisnik sistema troši neuobičajeno velik dio resursa na štetu ostalih.

U Habitatu smo morali odvagnuti sve ove kompromise kako bismo osmislili pouzdan i efikasan sistem za pohranu velikih razmjera. Danas je Habitat višekorisnički sloj baze podataka za mnoge proizvode kompanije OpenAI, ali do toga smo došli kružnim putem: od jednog višekorisničkog Azure Cosmos DB kontejnera, preko zasebnih pozadinskih kontejnera za pojedinačne korisnike, do povratka na višekorisnički kontejner kao zadani izbor. Još smo na samom početku razvoja višekorisničkog pristupa u Habitatu. Podržavamo velik broj slučajeva upotrebe, ali smo ulaganja u ovu oblast uspjeli odgoditi koristeći ugrađene osnovne mehanizme Azure Cosmos DB-a gdje god je to bilo moguće.

Kratak uvod u Azure Cosmos DB kontejnere

Prije nego što opišemo naš razvojni put s Azure Cosmos DB-om, evo nekoliko osnovnih informacija:

  • Azure Cosmos DB račun definira skup kontejnera i pravila replikacije

  • Svakom kontejneru dodjeljuje se određeni protok izražen u jedinicama zahtjeva u sekundi (RU/s)

  • Podaci u svakom kontejneru pohranjuju se uobičajenom podjelom prema zadanom ključu logičke particije, uz dokumentirana ograničenja pohrane i protoka po ključu

  • Azure Cosmos DB raspoređuje ključeve logičkih particija na manji broj pozadinskih fizičkih particija. Te particije dijeli na više fizičkih particija kada količina pohranjenih podataka premaši prag ili kada kontejneru treba više fizičkih particija da bi održao dodijeljeni protok

Faza I: Oslanjanje na osnovne mehanizme Azure Cosmos DB-a

Prvobitno smo propuštali sva klijentska opterećenja, oslanjajući se na navedeno ograničenje od 10K RU/s po ključu logičke particije da uspori dolazne zahtjeve kada je potrebno. Na početku smo također koristili samo jedan zadani Azure Cosmos DB kontejner u svakom računu. To je funkcioniralo dovoljno dobro, ali se pokazalo problematičnim iz nekoliko razloga:

Ograničenja ključeva logičkih particija

Zbog ranih odluka pri dizajnu API-ja, izbor ključa logičke particije prepustili smo direktno klijentima. Zbog toga često dolazi do kolizija na uobičajenim ključevima particija, poput user_id ili workspace_id, između različitih slučajeva upotrebe proizvoda. Budući da su ti slučajevi upotrebe dijelili ograničenja Azure Cosmos DB-a na istim ključevima logičkih particija, ovakav dizajn ograničavao je ukupan protok za pojedinog korisnika.

Jedan od čestih problema pri skaliranju Postgresa, prije prelaska na Habitat i Azure Cosmos DB, bio je da veliki broj zahtjeva izrazito aktivne organizacije ili za izrazito aktivan ključ — dakle jednog korisnika koji stvara nesrazmjerno veliko opterećenje — može oboriti cijelu bazu podataka. Uložili smo znatan zajednički trud u keširanje tih ključeva i uvođenje mehanizma zakupa pri promašajima keša, kako opterećenje nastalo zbog promašaja ne bi preopteretilo osnovnu bazu podataka.

Figure 02a · Logical partition key limits

Different clients, the same partition key

Cosmos DB containerPhysical partitionPK: user-id-28104CapacityMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedMemory / dreaming : capacity usedConversationsSuccess rateResponses returned in this animation loop—AuthSuccess rateResponses returned in this animation loop—Memory / dreamingSuccess rateResponses returned in this animation loop—

Bučni susjedi

Iako se dokumentirana ograničenja veličine podataka i protoka odnose na ključeve logičkih particija, ograničenja se zapravo provode na fizičkoj particiji. U praksi to znači da logičke particije ne mogu dostići 10.000 RU/s. Umjesto toga, ograničenja fizičke particije dijele sa svim ostalim ključevima logičkih particija smještenim na njoj.

Zbog toga su bučni susjedi mogli utjecati na mnoge nepovezane ključeve logičkih particija, pa su radna opterećenja nad podacima za usko specijalizirane funkcije proizvoda ometala osnovne tokove prijave i registracije.

Figure 02b · Noisy neighbors

Different users, the same physical partition

Cosmos DB containerPhysical partitionPKs: user-id-28104, user-id-10384Conversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversations user-id-28104: capacity usedConversationsuser-id-28104Success rateResponses returned in this animation loop—Conversationsuser-id-10384Success rateResponses returned in this animation loop—

Slabe particije

Ograničenje protoka pojedine fizičke particije također je promjenjivo i zavisi od ukupnog protoka dodijeljenog Azure Cosmos DB kontejneru. Dodijeljeni protok kontejnera raspoređuje se približno ravnomjerno među njegovim fizičkim particijama.

Kako količina podataka raste, fizičke particije se dijele, pa se njihov ukupan broj povećava, dok ukupni dodijeljeni protok ostaje nepromijenjen. Posljedica je da se efektivno ograničenje protoka po particiji smanjuje kako količina podataka raste.

Za naše slučajeve upotrebe koji pohranjuju velike objekte nalik blobovima i zauzimaju najviše prostora, to stvara problem u kojem sam rast pohranjenih podataka smanjuje kapacitet protoka za aktivna radna opterećenja, čak i kada učestalost zahtjeva i korištenje ostaju stabilni.

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.

Before split: 10K RU/s capacity

After split: 5K RU/s capacity × 2 partitions

RU/s05K6K10K200200429

Faza II: Pokušaj izolacije radnih opterećenja i korištenja zasebnih resursa

Odvojeni kontejneri pomažu da se djelimično riješe ova ograničenja ključeva particija i problemi bučnih susjeda. Svakom odvojenom kontejneru mogu se dodijeliti vlastite nezavisne fizičke particije, pa samo različita radna opterećenja unutar tog kontejnera mogu biti bučni susjedi ili imati preklapanja u prostoru ključeva particija. S druge strane, postavljanje novih kontejnera zahtijeva dodatni rad: kapacitet se mora zasebno planirati za svaki kontejner. Zato kontejnere želimo kreirati samo tamo gdje to ima smisla prema granicama servisa ili slučaja upotrebe.

Počeli smo koristiti odvojene Azure Cosmos DB kontejnere za najkritičnije nove slučajeve upotrebe koji su zahtijevali snažnu izolaciju. Uz skriptu za upravljanje slabim particijama, koja je usklađivala ukupan dodijeljeni protok svakog kontejnera s brojem njegovih fizičkih particija, uglavnom smo izbjegli sve probleme s kojima smo se suočavali.

Međutim, budući da smo počeli s jednim zadanim kontejnerom, mnogi stariji kritični slučajevi upotrebe nažalost su ostali vezani za njega sve dok se ne izvrši migracija podataka. Kako bismo zaštitili kritične servise koji su se i dalje oslanjali na podatke u zajedničkom zadanom kontejneru, timovima smo često savjetovali da kreiraju odvojene kontejnere za nove servise ili značajne funkcije proizvoda. Kako smo rasli, rastao je i pritisak na zadani kontejner, kao i broj incidenata u produkciji. Počeli smo postavljati kontejnere za svaki novi servis ili veliku funkciju proizvoda samo da bismo zadani kontejner zaštitili od dodatnog opterećenja.

To nas je poštedjelo mnogih prekida rada cijelog sistema, ograničavajući posljedice na prekide ili pogoršanje rada pojedinih funkcija ili servisa. Ipak, dodatni posao oko postavljanja novih kontejnera na kraju je postao problem:

Nedostatak stabilnog ukupnog rasta

U starom zajedničkom zadanom kontejneru bilo je malo vjerovatno da bi rast nekog novog slučaja upotrebe s 0 na milion upita u sekundi (QPS) značajno promijenio ukupno korištenje. Međutim, u izoliranom kontejneru rast novog slučaja upotrebe s 0 na milion QPS mogao je predstavljati 1.000 puta veće opterećenje od početnog, koje je poticalo samo od internog testiranja proizvoda.

Uz namjenske kontejnere, timovi su sada morali voditi računa da prije lansiranja dodijele kontejnerima očekivani kapacitet protoka. Timovi za razvoj proizvoda često bi pustili funkcije u produkciju, a zaboravili unaprijed povećati kapacitet. Tako bismo na dan lansiranja bili na sastancima za rješavanje ozbiljnih incidenata, pokušavajući u posljednji čas povećati kapacitet kontejnera.

Time zbog bolje izolacije gubimo jednu od ključnih prednosti višekorisničkih sistema: kombiniranje različitih radnih opterećenja na zajedničkim resursima.

Figure 03 · Lack of stable aggregate growth

The same workload, different headroom

1K RU/s during load testing → 1M RU/s at launch

Shared container

100M RU/s capacity · 80% utilized

Load test

1K20M=

0.005%

of headroom

Launch

1M20M=

5%

of headroom

New dedicated container

10K RU/s capacity · no other workloads

Load test

1K10K=

10%

of headroom

Launch

1M10K=

10,000%

of headroom

Planiranje kapaciteta

S vremenom je praćenje korištenja namjenskih kontejnera zahtijevalo i detaljno poznavanje proizvoda kako bi se znalo kada će se saobraćaj promijeniti ili porasti.

Možemo ponuditi osnovnu skriptu upravljačkog sloja za povećanje dodijeljenog protoka svakog kontejnera prema trendovima rasta. Međutim, bez stabilnog ukupnog rasta, njihovo pravilno skaliranje praktično je uključilo svaki tim za razvoj proizvoda u kompaniji OpenAI u planiranje kapaciteta.

Ovaj pristup nije mogao pratiti rast organizacije jer se pažnja koju su timovi posvećivali dodjeli Azure Cosmos DB resursa za svoje servise znatno razlikovala.

Faza III: Višekorisnički pristup kao zadani izbor, uz mogućnost premještanja podataka

Kako je organizacija rasla, bilo je sve teže rješavati te operativne probleme. Bez jednog centralnog tima zaduženog za planiranje, mnogi timovi planirali su loše. Zato smo se na kraju vratili višekorisničkom rješenju i blisko sarađivali s timom za Azure kako bismo riješili prvobitne probleme dijeljenja resursa:

Ograničavanje zahtjeva za aktivne ključeve

Prioritetno ograničavanje zahtjeva za najaktivnije ključeve sprečava bučne susjede da potroše sav raspoloživi protok pojedine fizičke particije. Time se smanjuje njihov utjecaj, zbog kojeg jedan vrlo aktivan ključ može izazvati probleme u cijelom sistemu.

Kvalitet usluge (QoS)

QoS s razvrstavanjem zahtjeva po prioritetima na sličan način sprečava vanmrežna radna opterećenja, poput masovnih unosa ili izdvajanja podataka, da iskoriste sav protok pojedine fizičke particije. Dodjeljivanjem nižeg prioriteta tim zahtjevima, oni se ograničavaju prvi. Tako se izbjegava ograničavanje interaktivnih zahtjeva višeg prioriteta koji služe krajnjim korisnicima.

Režim bez upravljanja serverima

Azure Cosmos DB već je imao režim bez upravljanja serverima koji bi riješio naš problem slabih particija u režimu s unaprijed dodijeljenim kapacitetom. Međutim, imao je veliki nedostatak: skalirao se samo prema iskorištenosti pohrane i ograničavao korištenje RU-a na 5K RU/s po fizičkoj particiji. Time bismo riješili problem slabih particija, ali ne bismo mogli povećavati kapacitet za slučajeve upotrebe s velikom potrošnjom RU-a.

Tim za Azure Cosmos DB izgradio je za nas novi, poboljšani režim bez upravljanja serverima, koji je svakoj fizičkoj particiji omogućio skaliranje do 10K RU/s. Uz podjelu prema iskorištenosti pohrane, uveo je i podjelu prema potrošnji RU-a, pa više nismo morali ručno pratiti i povećavati kapacitet kontejnera.

Zahvaljujući ovim promjenama mogli smo se vratiti na jedan zajednički kontejner. To je timovima za razvoj proizvoda znatno pojednostavilo početno i kontinuirano planiranje kapaciteta, uz očuvanu izolaciju radnih opterećenja. U mjesecima nakon toga nismo imali nijedan incident povezan s dodjelom resursa ili bučnim susjedima, uprkos ubrzanom razvoju proizvoda.

Veća pouzdanost kroz zajedničko upravljanje servisima

Kada kompanije dostignu razmjere kompanije OpenAI, upravljani servisi postaju manje „upravljani“. Mnoga radna opterećenja izlaze iz uobičajenih okvira infrastrukture pružaoca usluga u oblaku. Kako je OpenAI postao jedan od najvećih korisnika Azure Cosmos DB-a, za uspješan rad bio je potreban drugačiji pristup: zajednički testovi, zajedničke nadzorne ploče, direktni kanali između inženjera i zajednička odgovornost za vrste kvarova koje se javljaju samo pri našim razmjerama. Danas naš najveći Azure Cosmos DB račun pohranjuje desetine petabajta podataka i obrađuje više od 20 miliona QPS. Koliko znamo, jedina smo kompanija koja koristi Azure Cosmos DB u ovim razmjerama.

Krajem 2024. godine regionalni prekid rada jasno je pokazao zašto je ova saradnja neophodna. Tada je nestanak struje pogodio primarnu Azure regiju jednog od naših najvećih Azure Cosmos DB računa. Tokom prebacivanja na rezervnu regiju shvatili smo da bi našim najvećim računima za to trebalo nekoliko sati. Ni naš tim ni tim za Azure Cosmos DB to nisu testirali u našim razmjerama.

Otprilike mjesec kasnije, pri vraćanju tih računa u prvobitnu regiju, izazvali smo još jedan ozbiljan prekid rada. Navala konekcija prema prvobitnoj regiji preopteretila je njen Azure Cosmos DB pristupnik. Zbog specifičnosti načina na koji je Azure Cosmos DB klijent u režimu pristupnika obrađivao prebacivanja, svi klijenti odmah su uspostavili konekcije i slali zahtjeve u prvobitnu regiju, iako se u nju vratio samo dio fizičkih particija.

Pri svakom prekidu rada i OpenAI i Azure proveli su svoje postupke upravljanja incidentima, utvrdili niz osnovnih uzroka i primijenili ispravke. Ali ti prekidi bili su simptomi šireg sistemskog problema u načinu na koji su naš tim i tim za Azure Cosmos DB radili i testirali. U početku nam je korištenje upravljanih servisa omogućavalo da brzo napredujemo i usredotočimo se na poslovne ciljeve. Pri velikim razmjerama upravljani servisi zahtijevaju više našeg angažmana i blisko povezivanje s pružaocem usluge na svim nivoima, od dizajna do operativnog rada.

Danas inženjerski timovi Habitata i Azurea zajednički nadziru svaki sloj Habitata, od naših servisnih slojeva do fizičkih slojeva pohrane Azure Cosmos DB-a. Za operativni rad i testiranje promjena koristimo Azure Cosmos DB račun veličine produkcijskog, ali izvan produkcije. Zajedno testiramo i unapređujemo SDK-ove te utvrđujemo najbolje prakse za skaliranje i određivanje kapaciteta naših Azure Cosmos DB računa. Naši inženjeri direktno komuniciraju putem Teamsa, a omogućili smo čak i direktno pozivanje dežurnih kolega bez prolaska kroz nivoe podrške.

Tokom protekle godine uložili smo znatan zajednički trud u poboljšanje skalabilnosti upravljačkog sloja i pristupnika Azure Cosmos DB-a. Dodali smo zaštitu od preopterećenja i keširanje raznih metapodataka Azure Cosmos DB-a u pristupniku kako bismo zaštitili particiju s metapodacima, smanjili pritisak naše flote Python procesa habitat-service udruživanjem konekcija i njihovom češćom ponovnom upotrebom, smještali radna opterećenja na iste lokacije gdje god je to bilo moguće te odvajali kritična radna opterećenja od onih vanmrežnih pomoću zasebnih VPC-ova.

Ovaj nivo zajedničkog inženjerskog rada bio je ključan za stabilnost našeg Azure Cosmos DB-a tokom protekle godine. Svaki dovoljno velik ili važan sistem zahtijeva ovakav timski rad: prevazilaženje podjela u nadležnostima i saradnju preko organizacijskih granica.

Poboljšanje performansi na globalnom nivou

Kao što smo naveli u prvom dijelu, naša osnovna filozofija glasi: neka radi, neka radi brzo, neka radi jeftino. Prvo pouzdanost, zatim performanse, pa efikasnost. Habitat je postao ključna infrastruktura za OpenAI, pa je prvi prioritet bio osigurati njegovu pouzdanost. Kako se sistem stabilizirao tokom 2025. godine, a OpenAI širio globalno, latencija je postala sljedeće ograničenje za korisnike i timove za razvoj proizvoda.

Računarski kapaciteti i kapaciteti za pohranu često su se nalazili u različitim regijama, zbog čega su međuregijski zahtjevi bili neizbježni.

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.

ComputeStorageIllustrative routes · Longer journeys take more time

Geografske lokacije računarskih resursa i pohrane služe samo za ilustraciju.

Latencija je znatno varirala zavisno od toga gdje su podaci bili pohranjeni i gdje se zahtjev obrađivao. Kako bi zahtjevi prema Habitatu bili brzi, razvojni timovi oslanjali su se na dodatno keširanje na strani klijenta, grupiranje zahtjeva, smanjenje broja čitanja i upisa u bazu podataka te premještanje poslova izvan kritične putanje gdje god je to bilo moguće. Iako je to dovelo do zanimljivih rješenja otpornijih na probleme s bazom podataka, proizvodi su postali složeniji, a razvojne iteracije sporije. Time nije ostvaren cilj Habitata: omogućiti brz razvoj proizvoda bez potrebe za poznavanjem baze podataka.

To nam je jedan od glavnih prioriteta u 2026. godini. Razvili smo višeslojnu strategiju optimizacije performansi čitanja, koja čine više od 90% zahtjeva prema Habitatu:

Pohranjivati podatke blizu korisnika kada kapacitet to dozvoljava

Imamo više Azure Cosmos DB računa u različitim Azure regijama širom svijeta za korisnike koji imaju zahtjeve u pogledu rezidentnosti podataka. Čak i korisnicima bez strogih zahtjeva u pogledu rezidentnosti podataka, smještanje podataka u njihovoj blizini poboljšava iskustvo zahvaljujući nižoj latenciji.

U praksi to ne možemo široko primjenjivati izvan slučajeva koji zahtijevaju rezidentnost podataka jer smještaj ograničava fizički kapacitet infrastrukture u oblaku. Zbog veličine naših skupova podataka, mnoge regije ne mogu osigurati ogroman prostor za pohranu potreban za njihov proporcionalni udio korisničkog saobraćaja.

U regijama s ograničenim kapacitetom podatkovnih centara, napajanjem ili hlađenjem ponekad moramo birati: rezervirati kapacitet za lokalnu pohranu i nižu latenciju Habitata ili ga iskoristiti za dodatne računarske resurse za obradu zahtjeva, a zahtjeve za pohranu usmjeravati dalje.

Zato odluke o smještaju često predstavljaju kompromis između: A) optimizacije latencije za različite proizvode i grupe korisnika i B) ukupnog kapaciteta za pohranu i obradu.

Široko replicirati samo najmanje skupove podataka i one najosjetljivije na latenciju

Za radna opterećenja kod kojih je latencija najkritičnija, poput metapodataka za autentifikaciju potrebnih za svaki zahtjev, smanjujemo povratno vrijeme komunikacije (RTT) između računarskih resursa i Habitata koristeći Azure Cosmos DB račune s velikim brojem replika u brojnim sekundarnim regijama. Neki računi repliciraju podatke u svih 40 Azure regija u kojima obrađujemo saobraćaj, a drugi u najmanje jednu regiju na svakom kontinentu.

Morali smo ranije nego što smo željeli u Habitat ugraditi sloj za premještanje i usmjeravanje podataka koji je nevidljiv klijentima, kako bismo mogli premještati skupove podataka između računa s različitim topologijama replikacije.

Ipak, i ovaj pristup na kraju ograničava kapacitet, pa je sveden na nekoliko pažljivo odabranih skupova podataka.

Za sve ostalo osloniti se na integrirano keširanje

U Habitatovim radnim opterećenjima izrazito dominira čitanje: aplikacije stalno dohvaćaju postavke, stanje i druga svojstva. Nesrazmjerno velik dio saobraćaja potiče od relativno malog radnog skupa tipova podataka kojima se često pristupa. Zbog toga je sistem posebno pogodan za distribuirano keširanje. Iako keširanje poboljšava performanse infrastrukture unutar jedne regije, koristi su još veće pri radu u više regija, gdje se njime može „sakriti“ latencija međuregijske komunikacije.

U Habitat smo integrirali distribuirani bočni sloj keša. On čuva kopije nedavno dohvaćenih objekata i veza na Valkey serverima u našoj infrastrukturi, blizu mjesta gdje se obrađuju korisnički zahtjevi. Ovakvi keševi obično koriste vrijeme važenja (TTL), kojim se uspostavlja kompromis između stope pogodaka i zastarjelosti podataka. Kratak TTL smanjuje zastarjelost, ali i korist od keširanja, jer stavke brzo istječu iz keša i moraju se češće ponovo dohvaćati. Duži TTL povećava stopu pogodaka, ali duže isporučuje zastarjele podatke, što narušava korisničko iskustvo i dovodi do nepredvidivog ponašanja proizvoda.

Drugi pristup je eksplicitno poništavanje stavki keša kada aplikacija upisuje promjene u iste osnovne podatke. To znatno poboljšava svježinu keširanih podataka, ali može biti teško pravilno implementirati. I dalje ostaje osjetljivo na niz rubnih slučajeva, poput djelimičnih kvarova, zbog kojih keš ostaje zastario. Implementacije u više regija dodatno otežavaju ove probleme zbog manje pouzdanih međuregijskih mreža i utrkivanja ažuriranja keša s replikacijom osnovne pohrane. Dodavanje TTL-a ograničava maksimalnu zastarjelost, ali i dalje podrazumijeva isti ranije opisani kompromis.

Odabrali smo napredniji pristup poništavanju, slijedeći primjer sistema poput Metinog TAO-a. Habitatov integrirani keš oslanja se na bilježenje promjena podataka (CDC) putem toka promjena Azure Cosmos DB-a. Tako se poništavanja globalno prenose u roku od nekoliko sekundi, čime se postiže visoka stopa pogodaka uz malu zastarjelost. Servis u našoj infrastrukturi obrađuje taj tok promjena i poništava stavke u lokalnim keševima kada se osnovni podaci ažuriraju. To uzrokuje promašaj pri sljedećem čitanju tih podataka, nakon čega se keš popunjava njihovom najnovijom verzijom.

Smanjite opterećenje proxyja uz Rust

Latenciju smo također znatno smanjili uklanjanjem dodatnog opterećenja u samom servisu Habitat: prepisali smo kod u Rustu, koji je brži od prvobitnog Pythona.

Ove promjene zajedno su smanjile ukupnu globalnu latenciju čitanja p50 s približno 120 ms na približno 10 ms, što je poboljšanje od 12 puta otkako smo se početkom ove godine posvetili performansama.

Figure 05 · Improving performance at a global scale

p50 latency for reads

Three major design changes improved read latency

roughly 120 ms → roughly 10 ms

12x improvement

Milliseconds020406080100120140160Vrijeme123
  1. critical data replicated into nearby geos
  2. in-region caching launched
  3. rust rewrite launched

Iako je keširanje drastično smanjilo medijalnu latenciju, najsporiji zahtjevi i dalje moraju dohvaćati nekeširane podatke iz osnovne pohrane, često iz udaljenih regija. Kako postaje dostupno više kapaciteta i poboljšavamo efikasnost pohrane, planiramo riješiti temeljniji izazov: od samog početka smještati podatke bliže mjestu s kojeg će im se pristupati.

Skaliranje bilježenja promjena podataka

Pouzdan i skalabilan CDC — prenošenje promjena iz baze podataka u nizvodne sisteme — ključan je za mnogo više od same Habitatove strategije keširanja. Milioni zabilježenih promjena u sekundi, iz hiljada kontejnera i miliona njihovih particija, prolaze kroz više od stotinu Kafka tema. One također pokreću sekundarne indekse s eventualnom konzistentnošću, tokove premještanja podataka, vanmrežnu analitiku i druge funkcije proizvoda u stvarnom vremenu. Kako se naša osnovna infrastruktura širila globalno, praćenje promjena redova postajalo je sve složenije. Ako klijent želi registrirati povratnu funkciju koja se izvršava kad god se promijene redovi njegovog tipa, prvo mora, između ostalog, utvrditi koji Cosmos računi i kontejneri sadrže njegove podatke te koja instanca CDC servisa u odgovarajućim regijama prati te kontejnere. Mora i pravilno skalirati flotu radnih procesa CDC servisa, Kafku i vlastiti potrošački proces. Cilj naše CDC platforme je sakriti svu tu složenost od razvojnih timova i ponuditi jednostavan interfejs: klijenti registriraju funkciju koja će se pozivati za njihove promijenjene redove, a mi preuzimamo sve povezivanje i skaliranje.

Interni upravljački sloj stalno osigurava da se bilježe promjene iz svih potrebnih kontejnera, bira Cosmos regije iz kojih će se čitati i efikasno raspoređuje posao među hiljadama radnih procesa u više geografskih regija. Korištenje regija s replikama i čitanja toka promjena nižeg prioriteta štiti Habitatov saobraćaj osjetljiv na latenciju od pozadinskog bilježenja promjena. Padovi radnih procesa, problemi s kontejnerima, greške u spremištu zakupa, neispravne konfiguracije i kvarovi na odredištima stalno se javljaju u ovako velikoj floti. Povećali smo otpornost životnog ciklusa CDC radnih procesa i upravljanja zakupima, izolirali kvarove između tokova te ugradili zaštitne mehanizme za promjene konfiguracije i uvođenje novih verzija. Koristimo redove za neisporučive poruke kako trajne greške isporuke ne bi blokirale sve naredne poruke u redu. Regionalne prekide rada prevazilazimo prebacivanjem procesa za čitanje na druge Cosmos regije. Pri našim razmjerama morali smo čak mijenjati Azureov CDC SDK kako bismo učinili zapisivanje kontrolnih tačaka efikasnijim: grupiramo ih u memoriji i samo povremeno zapisujemo u trajnu pohranu.

Iako je način na koji Habitat interno koristi Azure Cosmos DB složen, njegova glavna vrijednost uvijek je bila skrivanje infrastrukturnih detalja od razvojnih timova radi bržeg razvoja proizvoda. Naša CDC platforma slijedi isti princip.

Pogled u budućnost

Mali tim uspio je podržati brzo rastuću platformu za pohranu tako što je namjerno zadržao uzak opseg API-ja za pohranu, nastavio skalirati Python servis i prednost davao najhitnijim inženjerskim izazovima. Prvo smo se usredotočili na pouzdanost za kritični saobraćaj proizvoda, zatim na performanse čitanja za korisnike širom svijeta i na kraju na operativnu efikasnost pri velikim razmjerama. Ovaj pristup omogućio je brz rast i nove slučajeve upotrebe, uz poboljšanje pouzdanosti, performansi i brzine razvoja proizvoda.

Da bismo skalirali Habitat i pohranu razgovora za narednih milijardu korisnika, moramo riješiti izazov repliciranja podataka širom naše infrastrukture u još većim razmjerama. Kako bismo to preduhitrili, razvijamo vlastiti prilagođeni sistem za online pohranu eksabajtnih razmjera, optimiziran za velike Habitatove tipove podataka. Ovaj sistem, koji je još u razvoju, spaja jezgru RocksDB Cloud iz Rockseta s replikacijom zasnovanom na Raftu. Primjenjuje isti model dokumenata kao Azure Cosmos DB, ali koristi odvojenu pohranu i fizičku replikaciju kako bi smanjio potrebni kapacitet flash memorije, uz niži vršni broj upita u sekundi.

Ako vas zanima rad na ovakvoj podatkovnoj infrastrukturi u razmjerama na granicama današnje tehnologije, pogledajte naše otvorene pozicije⁠.

Autor

OpenAI