Rýchle škálovanie online úložiska pre vyše miliardu používateľov ChatGPT
Ako sme platformu aplikačného úložiska Habitat v Pythone prispôsobili bezprecedentnému rastu.
Autori: Jon Lee, Chaomin Yu a Ben Ries, členovia technického tímu
Každý produkt OpenAI závisí od rýchleho a spoľahlivého prístupu k údajom – či sa používateľ prihlasuje, kontroluje nastavenia Codexu alebo začína nový rozhovor v ChatGPT. Každá z týchto činností môže pred odpoveďou produktu vyžadovať mnoho samostatných vyhľadaní údajov. Ak sú tieto požiadavky pomalé, pomaly pôsobí aj produkt. Ak tieto požiadavky zlyhajú, produkt prestane fungovať úplne.
Habitat je platforma online úložiska, ktorú sme vytvorili, aby produkty OpenAI mohli rýchlo a spoľahlivo pristupovať k potrebným informáciám. Habitat dnes spracúva viac než 70 miliónov požiadaviek za sekundu a podporuje produkty, ktoré každý týždeň používa vyše miliardy ľudí v takmer 40 geografických oblastiach. Habitat bol prvýkrát spustený na podporu GPT na DevDay 2023 ako jednoduchá klientska knižnica v Pythone pripojená k jednej databáze. Dnes je to komplexný distribuovaný systém, ktorý obsluhuje viac než 500 petabajtov údajov.
Obrázok 01 · Čo je Habitat?
Platforma online úložiska
Habitat je platforma online úložiska, ktorú sme vytvorili, aby produkty OpenAI mohli rýchlo a spoľahlivo pristupovať k potrebným informáciám.
- Požiadavka
- Odpoveď
- Zmeny (CDC)
Vybudovať a prevádzkovať infraštruktúru v takomto rozsahu nie je jednoduché, no ani mimoriadne náročné. Naša situácia bola jedinečná bezprecedentným tempom, akým sme museli škálovať, aby sme zvládli ohromný rast používateľov a dopytu po produktoch a zároveň vybudovali vyspelú platformu. Systémoví inžinieri často navrhujú systém na desaťnásobný rozsah a dúfajú, že vydrží niekoľko rokov, kým sa pripravia na ďalšie desaťnásobné zväčšenie. V našom prípade sme za posledné tri roky každoročne vzrástli viac než desaťnásobne. Budovanie a prevádzka Habitatu preto boli sériou taktických rozhodnutí a ich správneho načasovania: každý komponent sme skúmali do najnižšej úrovne, aby sme z existujúceho technologického zásobníka vyťažili maximum, a zároveň sme odvracali nedostatok úložnej a výpočtovej kapacity, čím sme získavali čas na zásadné investície.
- Viac ako 70 miliónov
požiadaviek za sekundu
- Viac ako 1 miliarda
ľudí každý týždeň
- Viac ako 500 pentabajtov (PB)
údajov
S rastom OpenAI musel rásť aj Habitat: najprv dosiahnuť spoľahlivosť potrebnú pre kritickú produktovú prevádzku, potom rýchlosť pre používateľov na celom svete a napokon obratne fungovať v obrovskom rozsahu. Tento príspevok je prvou časťou dvojdielnej série o škálovaní online úložiska. Vysvetlíme, ako sa Habitat vyvíjal, prečo sme ho z knižnice zmenili na službu a ako sme zo služby napísanej v Pythone – jazyku nezvyčajnom pre tento typ systémov – vytvorili spoľahlivú vrstvu úložnej platformy.
V budúcom príspevku podrobne opíšeme, ako sme vo veľkom rozsahu zabezpečili spoľahlivosť viacerých nájomníkov, našu viacvrstvovú stratégiu optimalizácie čítania a rozšírenie spolupráce s Azure Cosmos DB na spoľahlivé zvládanie bezprecedentného dopytu.
Habitat vznikol z jednoduchej myšlienky: produktoví inžinieri by sa nemali zaoberať správou databáz. Habitat bol prvýkrát spustený na podporu GPT na DevDay 2023 ako malá knižnica v Pythone, ktorá komunikovala s hlavným serverom ChatGPT. Podporovala malú množinu operácií, ktoré sa na pozadí mapovali na databázovú aplikáciu Azure Cosmos DB.
Úlohou knižnice bolo ponúknuť produktovým tímom jednoduchý spôsob ukladania a načítavania údajov bez potreby ovládať technické detaily v pozadí. Habitat zabezpečoval všetku potrebnú prácu: určoval typ údajov, odkiaľ sa majú načítať alebo kam uložiť, či je požiadavka povolená a podobne.
Produktoví inžinieri sa nemuseli zaoberať vyhľadávaním schémy, smerovaním, autorizáciou, šifrovaním, serializáciou, formovaním požiadaviek ani združovaním pripojení. Nemuseli dokonca ani riešiť, odkiaľ údaje pochádzajú – či z Azure Cosmos DB, vyrovnávacích pamätí alebo iných typov úložísk.
Obrázok 02 · Služba Habitat
Zjednodušený tok požiadavky Habitatu
Oddelením logiky úložiska do samostatnej služby sme vytvorili jediné miesto na riadenie nasadení, pozorovateľnosti a vylepšení platformy.
- Požiadavka
- Odpoveď
Táto knižnica v Pythone fungovala dobre a produktoví inžinieri v OpenAI si Habitat rýchlo osvojili, hoci neprebehla žiadna koordinovaná centrálna iniciatíva na odklon od samoobslužného Postgresu a Azure Cosmos DB.
S vývojom produktových potrieb mohli vývojári jednoducho dopĺňať do zdieľanej knižnice podporu funkcií, ako sú ukladanie do vyrovnávacej pamäte na strane klienta, kompresia či šifrovanie.
V polovici roka 2025 dosiahol Habitat hranice možností klientskej implementácie. S rastúcou zložitosťou vrstvy Habitat a pribúdajúcim počtom služieb OpenAI prestali byť spätne kompatibilné zmeny protokolu realizovateľné.
V jednom prípade sme chceli zmenšiť dosah výpadku ktorejkoľvek oblasti na naše najkritickejšie množiny údajov tým, že ich presunieme do súboru regionálne distribuovaných účtov Azure Cosmos DB. Táto zmena si vyžadovala pridať do klienta ďalšiu logiku smerovania, ponechať ju vypnutú pomocou príznaku funkcie, zabezpečiť jej nasadenie u všetkých klientov a potom príznak zapnúť.
Koordinácia nasadení v desiatkach služieb a spolupráca s každým tímom pri ich zavádzaní trvali celé dni. Pred zapnutím sme si uvedomili, že chceme zaviesť tieňovanie, aby sme overili správnosť logiky delenia. Jeho zavedenie trvalo ďalších pár dní. Oprava chyby v niečom, čo sme spätne vyhodnotili ako nesprávne? Ďalších pár dní. Napokon sme boli pripravení príznak zapnúť, no jeden z tímov z nesúvisiacich dôvodov vrátil svoju službu k staršiemu chybnému klientovi a spôsobil presne ten výpadok, ktorému sme sa tak usilovne snažili vyhnúť.
Zmeny klientskej knižnice si vyžadovali zložitú koordináciu desiatok služieb. Tento proces bol čoraz krehkejší, neefektívnejší a náchylnejší na prevádzkové zlyhania. Aby sme pri budúcich nasadeniach obmedzili toto prevádzkové rozvetvenie, rozhodli sme sa z Habitatu vytvoriť samostatnú službu.
Oddelením logiky úložiska do samostatnej služby sme vytvorili jediné miesto na riadenie nasadení, pozorovateľnosti a vylepšení platformy. Namiesto správy roztrieštených aktualizácií sme mohli vylepšenia zavádzať centrálne a okamžite nimi zlepšiť každý produkt OpenAI.
Centralizovaná služba nám zároveň poskytuje jediný kontrolný bod na uplatňovanie najsilnejších mechanizmov zabezpečenia a ochrany osobných údajov. V službe Habitat môžeme centrálne presadzovať pravidlá riadenia prístupu, viesť audítorské záznamy a obmedzovať prístup k základným úložným zdrojom, ako je Azure Cosmos DB. Habitat zohráva kľúčovú úlohu pri ochrane používateľských údajov a zabraňuje neoprávnenému prístupu externých, interných aj agentových aktérov.
Vedeli sme, že potrebujeme službu, no zatiaľ sme nechceli opustiť Python, hoci jeho použitie pre službu prinášalo dodatočnú réžiu. Použitie Pythonu pre službu s vysokou priepustnosťou zvýšilo latenciu siete a oproti lokálnemu spúšťaniu knižnice výrazne predražilo škálovanie procesora a pamäte. Uvedomovali sme si tiež, že pri stonásobnom rozsahu by už neefektívnosť Pythonu nebola prijateľná, takže budúce prepísanie bolo takmer isté.
Považovali sme to však za strategické prijatie technického dlhu. Naším hlavným cieľom vtedy nebola optimalizácia nákladov ani zdrojov, ale odstránenie prekážok pre produktových vývojárov a stabilizácia platformy. Krátkodobým prijatím výkonnostných kompromisov služby v Pythone sme mohli uprednostniť naliehavejšie výzvy, ustáliť naše kľúčové API a vybudovať robustnú infraštruktúru.
Zároveň sme stavili na to, že rýchly pokrok našich vlastných modelov na programovanie nám v budúcnosti zjednoduší technický postup. Predpokladali sme, že keď bude potrebné úplne prejsť z Pythonu, Codex a GPT nám túto migráciu umožnia zvládnuť. Táto stávka sa napokon vyplatila.
Prevádzkovať Habitat ako službu v Pythone nebolo z hľadiska výkonu ideálne, no bolo to nevyhnutné rozhodnutie. Python nám umožňuje postupovať rýchlo, to však neznamená, že sme mohli zahodiť opatrnosť a akceptovať výrazne vyššie latencie. Keď priemerná požiadavka používateľa vyvolá stovky databázových volaní, používateľ pocíti práve to najpomalšie. Zistili sme, že hlavnou výzvou pri prevádzke služby v Pythone v tomto rozsahu je riadenie chvostových latencií.
Asyncio pomáha Pythonu súbežne vykonávať úlohy viazané na vstup a výstup, nedokáže však obísť Python GIL ani zabezpečiť paralelné spracovanie procesorom. Okrem sprostredkovania požiadaviek s intenzívnym vstupom a výstupom zabezpečuje Habitat množstvo procesorovo náročných činností a úloh na pozadí: smerovanie, kompresiu, šifrovanie, kontrolné súčty, kontrolu stavu nadväzujúcich služieb, tieňovanie požiadaviek a hedging.
Pri takom množstve procesorovo náročných operácií a úloh na pozadí môže oneskorenie plánovania asyncio ľahko tvoriť väčšinu chvostovej latencie požiadaviek. Pred ladením prvého nasadenia služby sme v trasovaniach požiadaviek s latenciou p99 a vyššou videli, že hoci nadväzujúce úložisko odpovedalo rýchlo, požiadavky často uviazli pri čakaní na opätovné naplánovanie príslušnej korutiny, ktorá mala odpoveď analyzovať.
Obrázok 03 · Sledovanie oneskorenia asyncio
Súbežnosť nie je paralelné spracovanie procesorom
Asyncio v Pythone umožňuje súbežne spracúvať požiadavky, no vo vlákne procesora sa naraz vykonáva iba jedna. Ak treba vykonať veľa práce procesorom, výrazne to ovplyvňuje latenciu požiadaviek.
Nízka záťaž procesora
Krátke kroky Pythonu; čakania na I/O sa prekrývajúVysoká záťaž procesora
Dlhé kroky Pythonu nechávajú pripravené odpovede čakaťPri službách v Pythone v OpenAI považujeme popri štandardných metrikách využitia a vyťaženia pamäte, procesora, siete a disku za nevyhnutné sledovať aj slučku asyncio a mieru jej vyťaženia a podľa toho systém ladiť.
Pravidelným plánovaním úloh na pozadí a zaznamenávaním rozdielu medzi očakávaným a skutočným časom vykonania dokážeme v reálnom čase empiricky merať oneskorenie plánovania slučky udalostí. Pri vysokom využití a mnohých náročných úlohách stačí aj pomerne malý počet súbežných požiadaviek na proces, aby vzniklo výrazné kolísanie plánovania – až stovky milisekúnd a v okrajových prípadoch niekoľko sekúnd.
Preto každý proces obsluhuje len malý počet súbežných požiadaviek a namiesto toho výrazne horizontálne škálujeme počet pracovných procesov Pythonu.
Pri prvom spustení služby sme profilovaním procesora v živej prevádzke odhalili jednu z hlavných príčin vysokého oneskorenia asyncio, a teda aj vysokých chvostových latencií: pravidelnú analýzu JSON konfigurácií príznakov funkcií cez Statsig, nástroj na ich správu, A/B testovanie a ďalšie účely.
Statsig bol predvolene nastavený tak, aby každú minútu bez časového rozptylu zisťoval aktualizované konfigurácie, pričom konfigurácia obsahovala všetky produkčné pravidlá zo všetkých služieb. Inde sme sa v rámci architektúry rozhodli spúšťať až osem procesov Pythonu na pod, aby sme zvýšili využitie procesora a znížili latencie. V dôsledku tejto kombinácie sa v každom pode raz za minútu na chvíľu zastavili všetky pracovné procesy spracúvajúce rozpracované požiadavky a namiesto toho venovali procesorové cykly analýze obrovského konfiguračného súboru.
Keď nám profilovanie procesora pomohlo odhaliť hlavnú príčinu, náprava bola jednoduchá: nasadiť menšiu, cielenejšiu konfiguráciu, predĺžiť interval obnovovania a pridať podobným úlohám na pozadí časový rozptyl.
Na udržanie nízkeho oneskorenia asyncio je nevyhnutné aj dobre rozdeľovať požiadavky medzi serverové procesy. Bez správneho ladenia môže združovanie pripojení pôsobiť presne opačne.
Pri združovaní pripojení na strane klienta môže jeden klientsky proces s mnohými súbežnými požiadavkami vytvoriť len niekoľko serverových pripojení a celú svoju záťaž tak odosielať iba niekoľkým procesom. Pred úpravou vyvažovania záťaže sa využitie našej služby výrazne líšilo: niektoré chvostové procesy obsluhovali päť- až desaťnásobok priemerného počtu súbežných požiadaviek.
Odhalili sme to náhodou počas incidentu, keď aj po zastavení klienta, ktorý preťažoval časť služby, zostala skupina procesov v zhoršenom stave ešte dlho po odznení nárazovej prevádzky. Všimli sme si dokonca nekontrolované zhoršovanie týchto procesov, ktoré prijímali čoraz viac požiadaviek, až kým sme ich nereštartovali. Keď sa pod preťažil, určité správanie naň začalo smerovať ešte viac prevádzky. Išlo o typ zlyhania, ktorý niektorí naši kolegovia dobre poznali z predchádzajúcej práce: metastabilné zlyhanie(otvorí sa v novom okne).
Podozrievali sme fond pripojení a hypotézu sme otestovali obmedzením maximálneho času opätovného používania pripojenia. Zhoršovanie sa skutočne zmiernilo, čo potvrdilo správny smer vyšetrovania. Ďalším skúmaním sme zistili, že TCPConnector z knižnice aiohttp v Pythone predvolene opätovne používa pripojenia podľa LIFO: pre ďalšiu požiadavku vyberie naposledy vrátené pripojenie. Za bežných okolností je to rozumné predvolené nastavenie: opätovné používanie nedávnych pripojení umožňuje, aby dodatočným pripojeniam vytvoreným na zvládnutie nárazovej prevádzky vypršal čas nečinnosti, čím sa znižuje réžia ich udržiavania. V našom prípade to však spôsobilo metastabilné zlyhanie. Počas nárazovej vlny vracali požiadavky smerujúce na pomalšie preťažené servery pripojenia do fondu neskôr. Následné požiadavky ich preto vyberali častejšie a postupne koncentrovali ešte viac prevádzky na podoch, ktoré už mali problémy. Úprava fondu pripojení na opätovné používanie podľa FIFO prerušila túto spätnú väzbu a znížila aj odchýlky požiadaviek v ustálenom stave.
Obrázok 04A · Združovanie pripojení na strane klienta
LIFO posiela novú prácu späť pomalému procesu
Po nárazovej vlne požiadaviek vracajú pomalšie servery pripojenia do fondu ako posledné. LIFO podporuje hromadenie ďalšej práce práve na týchto pomalších serveroch.
Úvodná nárazová záťaž zasiahne A, B aj pomalší proces C.
Obrázok 04B · Združovanie pripojení na strane klienta
FIFO prerušuje spätnú väzbu opätovného používania pripojení
FIFO po nárazovej záťaži udržiava viac aktívnych pripojení, no záťaž spravodlivo rozdeľuje medzi všetky servery.
Úvodná nárazová záťaž zasiahne A, B aj pomalší proces C.
Dnes sa v celej infraštruktúre OpenAI spoliehame najmä na Istio a Envoy, ktoré zabezpečujú združovanie pripojení a lepšie stratégie vyvažovania zohľadňujúce záťaž serverov, čím sa tomuto problému úplne vyhýbame.
Vedľajším účinkom ladenia na nízke oneskorenie asyncio a veľkého počtu procesov Pythonu je, že nadväzujúce závislosti možno veľmi ľahko zahltiť obrovským množstvom pripojení, čo sa označuje ako „thundering herd“.
Bežné každodenné nasadenie môže bez nastavenia dostatočne pomalého priebehu spôsobiť výrazné výkyvy využitia procesora v dôsledku cyklického obnovovania pripojení. Únik pripojení zase môže vyradiť sieť presýtením brány NAT. Tieto problémy nie sú nezvyčajné ani pri iných službách, no rádovo vyšší počet procesov výrazne znižuje hranicu ich vzniku. Často sa tak presýtia sieťové zdroje, pri ktorých klienti podľa samotnej priepustnosti neočakávajú potrebu zvládať takúto záťaž v ustálenom stave.
Na maximalizáciu zlučovania pripojení sa spoliehame aj na Envoy. Používame ho na inováciu pripojení HTTP/1 z Pythonu na HTTP/2, aby sme využili multiplexovanie, a následne na ich združovanie a predĺženie životnosti. Envoy nám zároveň poskytuje centrálne miesto na zavedenie obmedzení frekvencie a prerušovačov obvodu, ktoré by boli v každom samostatnom procese Pythonu menej účinné.
Obrázok 05 · Zlučovanie pripojení
Rovnaké požiadavky, menej pripojení
Združovanie pripojení a multiplexovanie pripojení HTTP/2 pomáhajú znižovať zaťaženie nadväzujúcich služieb pripojeniami.
Jedným z dôvodov, prečo sme mohli Python škálovať až tak ďaleko, bolo obmedzené API Habitatu, vďaka ktorému sú náklady na požiadavky predvídateľné. Namiesto toho, aby Habitat klientom umožňoval vytvárať ľubovoľné dotazy SQL, ktoré by mohli viesť k rozsiahlemu skenovaniu tabuliek alebo spájaniu mnohých tabuliek, poskytuje jednoduché API NoSQL. Absencia výkonného API je vedomým kompromisom v návrhu Habitatu.
Optimalizujeme systém pre jednoduché, predvídateľné požiadavky s konštantnou náročnosťou. Podľa našich skúseností sa takéto systémy podstatne ľahšie škálujú a je náročné ich nesprávne navrhnúť či používať. Požiadavky s nepredvídateľným rozvetvením sú z prevádzkového hľadiska nebezpečné: komplikujú izoláciu a vyvažovanie záťaže a vytvárajú náhle nárasty latencie, na ktoré sa ťažko škáluje služba aj jej klienti.
Pred prechodom na Habitat a Azure Cosmos DB bola väčšina online údajov OpenAI uložená v Postgrese. V tom čase bolo jednoduché kontrolovať všetky zmeny dotazov a schémy a pred nasadením do produkcie overiť, že sa správajú primerane a pracujú s indexovanými údajmi. S rastom tímu a produktov sa to rýchlo stalo nezvládnuteľným a častou príčinou výpadkov: jediný nový náročný dotaz na frekventovanej ceste dokázal vyradiť databázu.
Problémom je nepomer nákladov: napísať dotazy SQL, ktorých vykonávanie je drahé a náročné, je lacné a jednoduché. V Habitate sa tomu vyhýbame a náročné dotazy sú na strane klienta úplne zjavné. Neexistujú tu neohraničené dotazy, ktoré by mohli Habitat preťažiť. Komplexné spojenia a prechody grafom vyžadujú, aby produktové tímy vykonali časť náročnej práce, čo celkovo podporuje efektívnejšie návrhy.
Habitat poskytuje API NoSQL postavené na typoch objektov a hrán definovaných klientmi, inšpirované systémom TAO(otvorí sa v novom okne). Klienti vopred definujú objekty, hrany a ich vzájomné vzťahy, nie však obsah jednotlivých typov. Výsledné vzťahy pripomínajú graf, samotný Habitat však okrem dotazovania na priame hrany konkrétneho objektu nepodporuje typické dotazy na prechod grafom.
Tento graf delíme tak, aby boli každý objekt a jeho príslušné hrany umiestnené spolu v oddiele na úrovni úložiska. Na úrovni databázy sa však cielene nesnažíme umiestniť objekty spolu so vzdialenými objektmi, na ktoré smerujú ich hrany. Výsledný model sa jednoducho delí na horizontálne škálovanie, no prechody grafom sú neefektívne, pretože konkrétny krok medzi objektmi môže vyžadovať načítanie z dvoch úplne odlišných účtov Azure Cosmos DB uložených v rôznych oblastiach.
Klientom s komplexnejšími potrebami dotazovania poskytujeme aj sekundárny offline pohľad na Habitat cez Rockset. Pomocou zachytávania zmien údajov (CDC) streamujeme zmeny z online úložiska do izolovaných inštancií Rockset takmer v reálnom čase. Každý klientsky tím zodpovedá za škálovanie vlastnej inštancie Rockset podľa svojich potrieb komplexného dotazovania.
Zriaďovanie Rocksetu prináša klientom dodatočné komplikácie, no v tejto chvíli ho považujeme za správny kompromis: predvolene ponúkame jednoduché dotazy a tým, ktorí potrebujú komplexné, poskytujeme alternatívu. Tento návrh izoluje naše online úložisko od analytických a vyhľadávacích úloh náročných na čítanie.
Odloženie prepísania Pythonu o rok nám počas hyperrastu umožnilo sústrediť sa na naliehavejšie a významnejšie výzvy. Keďže platforma dospievala, rast sa ďalej zrýchľoval a podľa počtu jadier išlo o druhú najväčšiu službu v OpenAI (a štvrtú podľa nasadenia Envoy), nastal čas opustiť Python. Na vrchole nám Python pomáhal obsluhovať viac než 20 miliónov požiadaviek za sekundu.
V druhom štvrťroku 2026 sa nám s iba dvoma inžiniermi, Codexom a GPT‑5.5 podarilo prepísať celú službu do Rustu. Nová služba v Ruste už spracúva 95 % našich produkčných požiadaviek. V najbližších týždňoch Python úplne vyradíme. Naše údaje ukazujú, že služba v Ruste využíva procesor šesťkrát a pamäť pätnásťkrát efektívnejšie než verzia v Pythone a má výrazne nižšiu priemernú aj chvostovú latenciu. O ďalšie poznatky sa plánujeme podeliť v budúcom blogovom príspevku.
Služba v Pythone – a teraz v Ruste – je len jednou stránkou Habitatu. V druhej časti tejto série o tom, ako sme rýchlo škálovali online úložisko pre viac než miliardu používateľov ChatGPT, sa budeme venovať vrstve úložiska a tomu, ako Habitat obsluhuje viac než 500 petabajtov údajov a vyše 70 miliónov požiadaviek za sekundu.
Ak chceš pracovať na systémoch OLTP v prelomovom rozsahu a zaujíma ťa takéto inžinierstvo, pozri si túto voľnú pozíciu v našom tíme.


