Брзо скалирање мрежног складишта за више од милијарду корисника ChatGPT‑а
Како смо Python платформу за складиштење апликација Habitat прилагодили незапамћеном расту.
Аутори: Џон Ли, Чаомин Ју и Бен Рис, чланови техничког особља
Сваки OpenAI производ зависи од брзог и поузданог приступа подацима — било да се неко пријављује, проверава подешавања Codex-а или започиње нови разговор у ChatGPT‑у. Свака од тих радњи може захтевати бројна засебна проналажења података пре него што производ одговори. Ако су ти захтеви спори, и производ делује споро. Ако ти захтеви не успеју, производ потпуно престаје да ради.
Habitat је платформа за мрежно складиште коју смо направили да би OpenAI производи брзо и поуздано приступали потребним информацијама. Habitat сада обрађује више од 70 милиона захтева у секунди и подржава производе које сваке недеље користи преко милијарду људи у готово 40 географских региона. Habitat је први пут покренут као подршка за GPT‑ове на догађају DevDay 2023, као једноставна Python библиотека на страни клијента повезана са једном базом података. Данас је то сложен дистрибуирани систем који опслужује више од 500 петабајта података.
Слика 01 · Шта је Habitat?
Платформа за мрежно складиште
Habitat је платформа за мрежно складиште коју смо направили да би OpenAI производи брзо и поуздано приступали потребним информацијама.
- Захтев
- Одговор
- Промене (CDC)
Изградња и управљање инфраструктуром ових размера није лак подвиг, али само по себи није ни нарочито тешко. Нашу ситуацију је чинила јединственом незапамћена брзина скалирања потребна да подржимо огроман раст броја корисника и потражње за производима, док смо истовремено градили зрелу платформу. Системски инжењери често пројектују за десетоструки обим и надају се да ће то потрајати неколико година док се припремају за следеће десетоструко повећање. Код нас је раст током последње три године сваке године био већи од десет пута. Зато се изградња и рад Habitat-а заснивају на низу тактичких одлука и њиховом редоследу: разумевању сваке компоненте до најнижег нивоа како бисмо извукли максимум из постојећег скупа технологија, уз ублажавање несташица складишног и рачунарског капацитета ради добијања времена за темељна улагања.
- 70M+
захтева у секунди
- 1B+
људи недељно
- 500 PB+
података
Како је OpenAI растао, морао је да расте и Habitat: најпре је постао довољно поуздан за критични саобраћај производа, затим довољно брз за кориснике широм света и, коначно, способан да вешто ради у огромним размерама. Ово је први текст дводелног серијала о томе како смо скалирали мрежно складиште. У овом тексту ћемо објаснити како се Habitat развијао, зашто смо га из библиотеке претворили у услугу и како смо услугу написану у неуобичајеном језику за овај технолошки скуп — језику Python — развили у поуздан платформски слој за складиштење.
У наредном тексту детаљно ћемо описати како смо обезбедили поузданост вишекорисничког окружења великих размера, слојевиту стратегију оптимизације читања и ширење сарадње са Azure Cosmos DB-ом ради поуздане обраде незапамћене потражње.
Habitat је настао из једноставне идеје: инжењери производа не треба да размишљају о управљању базом података. Habitat је први пут покренут као подршка за GPT‑ове на догађају DevDay 2023, као мала Python библиотека која је комуницирала са главним сервером ChatGPT‑а. Подржавала је мали скуп операција које су се у позадини пресликавале на апликацију базе података Azure Cosmos DB.
Задатак библиотеке био је да производним тимовима омогући једноставно чување и преузимање података без потребе да овладају детаљима система у позадини. Habitat је обављао неопходан посао: утврђивао врсту података, одакле треба да стигну или куда да оду, да ли је захтев дозвољен и тако даље.
Инжењери производа нису морали да брину о проналажењу шеме, усмеравању, ауторизацији, шифровању, серијализацији, обликовању захтева и обједињавању веза. Нису чак морали да разматрају одакле подаци долазе: из Azure Cosmos DB-а, кеша или других врста складишта.
Слика 02 · Услуга Habitat
Поједностављен ток захтева у Habitat-у
Издвајањем логике складиштења у самосталну услугу успоставили смо јединствену контролну тачку за примену, опсервабилност и унапређење платформе.
- Захтев
- Одговор
Ова Python библиотека добро је радила и инжењери производа у OpenAI-ју брзо су прихватили Habitat, иако није постојала централизована иницијатива да се напусте самостално коришћени Postgres и Azure Cosmos DB.
Како су се потребе производа развијале, програмери су лако могли да у заједничку библиотеку додају подршку за функције као што су кеширање на страни клијента, компресија и шифровање.
До средине 2025. Habitat је достигао границе имплементације на страни клијента. Како је слој Habitat-а постајао сложенији, а број OpenAI услуга растао, измене протокола компатибилне са старијим верзијама постале су неизводљиве.
У једном случају желели смо да смањимо домет отказа једног региона за најважније скупове података тако што бисмо их преселили на скуп регионално распоређених Azure Cosmos DB налога. Та измена је захтевала додавање логике усмеравања у клијент, искључене иза заставице функције, примену на све клијенте, па тек онда укључивање заставице.
Усклађивање примене у десетинама услуга и сарадња са сваким тимом трајали су данима. Пре укључивања схватили смо да желимо пресликавање захтева како бисмо проверили исправност логике дељења. И за то је било потребно још неколико дана. Исправка грешке у нечему за шта смо схватили да није исправно? Још неколико дана. Када смо коначно били спремни да укључимо заставицу, један тим је из неповезаних разлога вратио своју услугу на ранију верзију клијента са грешком и изазвао управо онај прекид који смо толико настојали да избегнемо.
Измене клијентске библиотеке захтевале су сложено усклађивање десетина услуга, а тај процес је постајао све крхкији, неефикаснији и подложнији оперативним отказима. Да бисмо смањили овакво оперативно ширење при будућим применама, одлучили смо да Habitat претворимо у засебну услугу.
Издвајањем логике складиштења у самосталну услугу успоставили смо јединствену контролну тачку за примену, опсервабилност и унапређење платформе. Уместо управљања расцепканим ажурирањима, побољшања смо могли да примењујемо централно и одмах помогнемо сваком OpenAI производу.
Централизована услуга пружа нам и једну контролну тачку за најснажније механизме безбедности и приватности података. Услуга Habitat омогућава нам да централно спроводимо смернице контроле приступа, водимо евиденцију ревизије и ограничавамо приступ основним ресурсима складишта као што је Azure Cosmos DB. Habitat има кључну улогу у заштити корисничких података и спречавању неовлашћеног приступа спољних и унутрашњих актера и агената.
Знали смо да нам је потребна услуга, али још нисмо желели да напустимо Python, упркос додатним трошковима које доноси у том облику. Коришћење језика Python за услугу високе пропусне моћи повећало је мрежно кашњење и знатно увећало трошкове скалирања CPU-а и меморије у односу на локално извршавање библиотеке. Осим тога, знали смо да неефикасност језика Python неће бити прихватљива при 100 пута већем обиму, па је накнадно преписивање било готово извесно.
Ипак, сматрали смо то стратешким прихватањем техничког дуга. Наш главни циљ тада није био оптимизација трошкова или ресурса, већ уклањање препрека за програмере производа и постизање стабилности платформе. Краткорочним прихватањем компромиса у перформансама Python услуге могли смо да се усредсредимо на хитније изазове, успоставимо основне API-је и изградимо робусну инфраструктуру.
Такође смо се прорачунато кладили да ће брз напредак наших модела за програмирање касније поједноставити технички пут. Кладили смо се да ће, када потпуна миграција са језика Python постане неопходна, Codex и GPT омогућити да је спроведемо. Та опклада се на крају показала исправном.
Покретање Habitat-а као Python услуге било би неоптимално по перформансама, али неопходно. Python нам омогућава да брзо напредујемо, али то не значи да смо могли да занемаримо опрез и прихватимо осетно већа кашњења. Када просечан кориснички захтев изазове стотине позива бази података, корисник осети онај најспорији. Установили смо да је главни изазов покретања Python услуге ових размера управљање кашњењима на крају расподеле.
Asyncio омогућава језику Python да истовремено извршава радна оптерећења ограничена улазом/излазом, али не заобилази Python GIL нити омогућава CPU паралелизам. Поред прослеђивања захтева са много улаза/излаза, Habitat обавља бројне CPU-интензивне задатке у позадини: усмеравање, компресију, шифровање, израчунавање контролних сума, проверу стања низводних система, пресликавање и заштитно дуплирање захтева.
Уз толико CPU-интензивних оптерећења и позадинских задатака у услузи, кашњење у распоређивању asyncio-а лако може постати главни узрок кашњења захтева на крају расподеле. Пре подешавања за прво покретање услуге, у траговима захтева са кашњењем p99 или већим видели смо да су се захтеви често заустављали иако је низводно складиште брзо одговорило, чекајући да одговарајућа корутина поново добије термин и рашчлани одговор.
Слика 03 · Праћење кашњења у asyncio-у
Истовременост није CPU паралелизам
Python asyncio омогућава истовремену обраду захтева, али се у сваком тренутку на CPU нити извршава само један захтев. Када има много CPU посла, то знатно утиче на кашњење захтева.
Мало CPU оптерећење
Кратки Python кораци; чекања на улаз/излаз се преклапајуВелико CPU оптерећење
Дуги Python кораци задржавају спремне одговореЗа Python услуге у OpenAI-ју, поред стандардних показатеља искоришћености и засићења меморије, CPU-а, мреже и диска, неопходно је пратити и asyncio петљу и њено оптерећење, па систем подешавати у складу с тим.
Периодичним распоређивањем позадинских задатака и бележењем разлике између очекиваног и стварног времена извршавања можемо емпиријски и у реалном времену мерити кашњење распоређивања петље догађаја. При високој искоришћености и великом броју скупих задатака, чак и умерен број истовремених захтева по процесу ствара значајно колебање распореда — до неколико стотина милисекунди, а у појединим граничним случајевима и неколико секунди.
Зато сваки процес опслужује само мали број истовремених захтева, док број Python радних процеса масовно хоризонтално скалирамо.
При првом покретању услуге, CPU профилисањем уживо открили смо један основни узрок великог кашњења asyncio-а, а тиме и великих крајњих кашњења: периодично рашчлањивање JSON конфигурација заставица функција преко Statsig-а, алатке за управљање заставицама функција, A/B тестове и друго.
Statsig је подразумевано био подешен да сваког минута, без временског одступања, проверава освежене конфигурације, а конфигурација је садржала сва продукциона правила за све услуге. У другом делу архитектуре одлучено је да се у сваком поду покреће до осам Python процеса како би се повећала искоришћеност CPU-а и смањила кашњења. Заједно, то је значило да би сваког минута у сваком поду наступио тренутак када сви радни процеси зауставе обраду текућих захтева и CPU циклусе троше на рашчлањивање огромне конфигурационе датотеке.
Када нам је CPU профилисање помогло да утврдимо основни узрок, решење је било једноставно: применити мању, циљану конфигурацију, продужити интервал освежавања и додати временско одступање оваквим позадинским задацима.
За одржавање малог кашњења asyncio-а неопходно је и добро распоређивање захтева међу серверским процесима; без подешавања, обједињавање веза може деловати супротно том циљу.
Код обједињавања веза на страни клијента, један клијентски процес који шаље много истовремених захтева може успоставити само неколико серверских веза и зато целокупно оптерећење послати на свега неколико процеса. Пре прилагођавања балансирања оптерећења, искоришћеност наше услуге веома је варирала, а неки процеси на крају расподеле опслуживали су 5–10 пута више истовремених захтева од просека.
То смо случајно открили током инцидента када је, упркос заустављању клијента који је преоптерећивао део услуге, један подскуп процеса остао деградиран дуго након налета саобраћаја. Заправо, приметили смо да се стање тих процеса неконтролисано погоршава и да примају све више захтева све док их нисмо поново покренули. Када би се под преоптеретио, неки механизам би усмеравао још више саобраћаја на њега. То је била врста отказа коју су неке колеге добро познавале из ранијег рада: метастабилни отказ(отвара се у новом прозору).
Посумњали смо на скуп веза и то проверили ограничавањем максималног трајања поновне употребе везе, што је заиста ограничило погоршање и потврдило правац истраге. Даља истрага показала је да Python aiohttp TCPConnector подразумевано користи LIFO поновну употребу веза: за следећи захтев бира се последња враћена веза. То је обично разуман подразумевани избор: поновна употреба недавних веза омогућава да додатне везе настале током налета саобраћаја истекну у мировању, чиме се смањују трошкови њиховог одржавања. У овом случају то је изазвало метастабилни отказ. Током налета захтева, захтеви послати споријим, преоптерећеним серверима касније су враћали везе у скуп, па су их наредни захтеви чешће бирали и постепено усмеравали још више саобраћаја на већ преоптерећене подове. Измена скупа веза тако да користи FIFO поновну употребу прекинула је ову повратну спрегу и смањила варијансу захтева у стабилном стању.
Слика 04A · Обједињавање веза на страни клијента
LIFO враћа нови посао спором процесу
После налета захтева спорији сервери последњи враћају везе у скуп. LIFO подстиче да се још више посла концентрише на истим споријим серверима.
Почетни налет стиже до A, B и споријег процеса C.
Слика 04B · Обједињавање веза на страни клијента
FIFO прекида повратну спрегу поновне употребе веза
FIFO после налета задржава више активних веза, али правично распоређује оптерећење на све сервере.
Почетни налет стиже до A, B и споријег процеса C.
Данас се углавном ослањамо на Istio и Envoy за обједињавање веза и боље стратегије балансирања које узимају у обзир оптерећење сервера широм OpenAI инфраструктуре, чиме потпуно избегавамо овај проблем.
Једна последица подешавања за мало кашњење asyncio-а и великог броја Python процеса јесте лако преоптерећење низводних зависности огромним бројем веза, познато као „налет крда“.
Редовна дневна примена, ако није подешена да буде спора, може изазвати значајно колебање CPU оптерећења услед непрестаног обнављања веза. Или цурење веза може оборити мрежу засићењем NAT мрежног пролаза. Ти проблеми нису ретки ни код других услуга, али десетоструко већи број процеса знатно снижава праг њиховог настанка и често засићује мрежне ресурсе за које клијенти, судећи само по пропусној моћи, не очекују да их морају подржати у стабилном стању.
На Envoy се ослањамо и да бисмо максимално објединили долазне везе. Користимо га да Python HTTP/1 везе надоградимо на HTTP/2 ради мултиплексирања, а затим те везе објединимо и продужимо им трајање. Envoy нам пружа и централно место за примену ограничења учесталости и аутоматских прекидача, који би били мање ефикасни у сваком самосталном Python процесу.
Слика 05 · Обједињавање долазних веза
Исти захтеви, мање веза
Обједињавање веза и мултиплексирање HTTP/2 веза смањују оптерећење везама на низводним системима.
Један од разлога што смо Python могли оволико да скалирамо јесте ограничени API Habitat-а, који трошак захтева чини предвидљивим. Уместо да клијентима омогући прављење произвољних SQL упита који могу довести до скенирања великих табела или спајања бројних табела, Habitat нуди једноставан NoSQL API. Одсуство моћног API-ја свесни је компромис у дизајну Habitat-а.
Тежимо оптимизацији за једноставне, предвидљиве захтеве са сталном количином посла. Према нашем искуству, такве системе је знатно лакше скалирати, а тешко их је погрешно направити или злоупотребити. Захтеви са непредвидљивим ширењем оперативно су опасни: отежавају изолацију и балансирање оптерећења и уводе нагле скокове кашњења за које је тешко скалирати и услугу и њене клијенте.
Пре преласка на Habitat и Azure Cosmos DB, већина OpenAI-јевих података на мрежи чувала се у Postgres-у. Тада је било лако прегледати све измене упита и шема и пре продукције проверити да ли се исправно понашају и користе индексиране податке. Како су тим и производи расли, то је брзо постало неизводљиво и често је изазивало прекиде јер би један нов, скуп упит на критичној путањи оборио базу података.
Проблем је у неравнотежи трошкова: јефтино је и лако написати SQL упите који су скупи и тешки за извршавање. У Habitat-у то избегавамо и чинимо скупе упите изузетно очигледним на страни клијента. Нема неограничених упита који могу преоптеретити Habitat, а сложена спајања и обиласци графова захтевају да производни тимови преузму део тежег посла, што подстиче ефикаснији дизајн у целини.
Habitat нуди NoSQL API заснован на типовима објеката и веза које дефинише клијент, по узору на TAO(отвара се у новом прозору). Клијенти унапред дефинишу објекте, везе и њихове међусобне односе, али не и садржај сваког типа. Добијени односи личе на граф, али Habitat не подржава уобичајене упите за обилазак графа, осим упита над директним везама одређеног објекта.
Овај граф делимо тако да се сваки објекат и његове везе налазе у истој партицији складишта, али на нивоу базе не настојимо да заједно смештамо објекте и удаљене објекте на које њихове везе упућују. Тако се модел лако партиционише ради хоризонталног скалирања, али су обиласци графа неефикасни јер сваки прелаз између објеката може захтевати преузимање из два потпуно различита Azure Cosmos DB налога у различитим регионима.
Клијентима са сложенијим потребама за упитима нудимо и секундарни ванмрежни приказ Habitat-а преко Rockset-а. Користимо бележење промена података (CDC) да бисмо промене из мрежног складишта готово у реалном времену преносили у изоловане Rockset инстанце. Сваки клијентски тим сам скалира своју Rockset инстанцу за сложене упите.
Омогућавање Rockset-а ствара додатне потешкоће клијентима, али сматрамо да је то сада прави компромис: једноставни упити су подразумевани, док они којима требају сложени имају излазну опцију. Овај дизајн изолује наше мрежно складиште од аналитичких и претраживачких оптерећења са великим бројем читања.
Одлагање преписивања језика Python за годину дана омогућило нам је да се током хиперраста усредсредимо на хитније и значајније изазове. Пошто је платформа сазрела, раст наставио да се убрзава, а услуга постала друга у OpenAI-ју по броју језгара и четврта по обиму Envoy-а, коначно је дошло време да напустимо Python. На врхунцу нам је Python омогућавао да обрађујемо више од 20 милиона захтева у секунди.
У другом кварталу 2026, са само два инжењера, Codex-ом и GPT‑5.5, успели смо да целу услугу препишемо у језику Rust. Нова Rust услуга сада обрађује 95% наших продукционих захтева; Python ћемо потпуно повући у наредним недељама. Наши подаци показују да Rust услуга шест пута ефикасније користи CPU и 15 пута ефикасније користи меморију од Python верзије, уз знатно мања просечна и крајња кашњења. Планирамо да у будућем тексту поделимо још сазнања.
Python услуга — а сада Rust услуга — само је један аспект Habitat-а. У другом делу серијала о брзом скалирању мрежног складишта за више од милијарду корисника ChatGPT‑а говорићемо о слоју складишта и о томе како Habitat опслужује више од 500 петабајта и преко 70 милиона захтева у секунди.
Ако желите да радите на OLTP системима граничних размера и занима вас ова врста инжењерства, погледајте отворено радно место у нашем тиму.


