Преминаване към основното съдържание
OpenAI

11 септември 2026 г.

Инженерство

Бързо мащабиране на онлайн хранилището за над 1 милиард потребители на ChatGPT

Как адаптирахме платформата си за съхранение Habitat на Python към безпрецедентния растеж.

От Джон Лий, Чаомин Ю и Бен Рийс, технически специалисти

Зареждане…

Всеки продукт на OpenAI зависи от бърз и надежден достъп до данни — независимо дали някой влиза в профила си, проверява настройките си за Codex, или започва нов разговор в ChatGPT. Всяко от тези действия може да изисква множество отделни извличания на данни, преди продуктът да отговори. Ако тези заявки са бавни, продуктът се усеща бавен. Ако тези заявки са неуспешни, продуктът спира да работи изцяло.

Habitat е платформата за онлайн съхранение, която създадохме, за да могат продуктите на OpenAI да осъществяват бърз и надежден достъп до необходимата информация. Habitat вече обработва над 70 милиона заявки в секунда и поддържа продукти, използвани от над 1 милиард души седмично в почти 40 географски региона. Habitat беше пусната първоначално за поддръжка на GPTs на DevDay 2023 като проста клиентска библиотека на Python, свързана с една база данни. Днес тя е сложна разпределена система, която обслужва над 500 петабайта данни.

Фигура 01 · Какво е Habitat?

Платформа за онлайн съхранение

Habitat е платформата за онлайн съхранение, която създадохме, за да могат продуктите на OpenAI да осъществяват бърз и надежден достъп до необходимата информация.

  • Заявка
  • Отговор
  • Промени (CDC)

Клиенти

Платформа за онлайн съхранение

Ресурси за съхранение

  • ChatGPT
  • API
  • Codex
  • Вътрешни услуги
  • И още

Habitat

  • КеширанеКешове
  • ACL политикиУпълномощаване
  • Разполагане и местонахождение на даннитеМестонахождение на данните
  • ШифрованеСигурност на данните
  • ИзолиранеМногонаемност
  • Ограничаване на честотатаОформяне на заявките
  • МаршрутизиранеТърсене в схемата · Местонахождение на данните
  • Azure Cosmos DBОнлайн съхранение
  • NanobaseОнлайн съхранение
  • ValkeyКешове
  • Хранилище за двоични обектиРесурси за съхранение
CDC услугиУлавяне на промени в данните
  • Databricks
  • Rockset
  • Kafka
  • И още

Изграждането и експлоатацията на инфраструктура в такъв мащаб не е лесно, но не е и особено трудно. Уникалното в нашия случай беше безпрецедентната скорост, с която трябваше да мащабираме, за да отговорим на огромния ръст на потребителите и продуктовото търсене, като същевременно изграждаме зряла платформа. Системните инженери често проектират за 10-кратен мащаб и се надяват той да е достатъчен за няколко години, докато се подготвят за следващото десетократно увеличение. В нашия случай през последните три години растежът ни надхвърляше 10 пъти всяка година. Затова изграждането и експлоатацията на Habitat се превърнаха в поредица от тактически решения и внимателно подреждане на стъпките: разбиране на всеки компонент до най-ниското ниво, за да извлечем максимума от съществуващия технологичен стек, като същевременно се справяме с недостига на капацитет за съхранение и изчисления и печелим време за фундаментални инвестиции.

  • 70 млн.+

    заявки в секунда

  • 1 млрд.+

    души седмично

  • 500 PB+

    данни

С растежа на OpenAI трябваше да расте и Habitat: първо да стане достатъчно надеждна за критичния продуктов трафик, след това достатъчно бърза за потребителите по света и накрая — да работи умело в огромен мащаб. Тази публикация е първата от поредица в две части за мащабирането на онлайн хранилището ни. Тук ще разкажем как се разви Habitat, защо я превърнахме от библиотека в услуга и как разширихме услуга, написана на необичаен за обслужващ стек език — Python — до надежден платформен слой за съхранение.

В следваща публикация ще разгледаме подробно как постигнахме надеждност при многонаемност в голям мащаб, многослойната ни стратегия за оптимизиране на производителността при четене и как разширихме партньорството си с Azure Cosmos DB, за да обработваме надеждно безпрецедентното търсене.

Какво е Habitat?

Habitat започна с проста идея: продуктовите инженери не бива да се занимават с управлението на бази данни. Habitat беше пусната първоначално за поддръжка на GPTs на DevDay 2023 като малка Python библиотека, която взаимодействаше с основния сървър на ChatGPT. Тя поддържаше малък набор от операции, които вътрешно се съпоставяха с приложението за бази данни Azure Cosmos DB.

Задачата на библиотеката беше да даде на продуктовите екипи лесен начин да съхраняват и извличат данни, без да овладяват подробностите на основната система. Habitat поемаше необходимата работа: определяше какъв е видът на данните, откъде трябва да дойдат или къде да отидат, дали заявката е разрешена и т.н.

Продуктовите инженери не трябваше да се занимават с търсене в схемата, маршрутизиране, упълномощаване, шифроване, сериализация, оформяне на заявки и обединяване на връзки. Дори не трябваше да мислят откъде идват данните: от Azure Cosmos DB, кешове или други видове хранилища.

Фигура 02 · Услугата Habitat

Опростен поток на заявките в Habitat

Като отделихме логиката за съхранение в самостоятелна услуга, създадохме единна точка за контрол на внедряванията, наблюдаемостта и подобренията на платформата.

  • Заявка
  • Отговор

Клиент

OpenAI

Azure Cosmos DB

Клиентски SDK за Habitat
envoy
  • habitat-serviceпроцес 1
  • habitat-serviceпроцес 2
  • habitat-serviceпроцес 3
habitat-envoy
  • habitat-cosmos-db-us0
  • habitat-cosmos-db-us1
  • habitat-cosmos-db-eu0

Тази Python библиотека работеше добре и Habitat бързо беше възприета от продуктовите инженери в OpenAI, въпреки че нямаше централизирана инициатива за отказ от самостоятелно използване на Postgres и Azure Cosmos DB.

С развитието на продуктовите нужди разработчиците можеха лесно да добавят към споделената библиотека поддръжка на функции като кеширане от страна на клиента, компресиране или шифроване.

Изграждане на услуга за по-добра поддръжка на множество сложни продукти

До средата на 2025 г. Habitat беше достигнала ограниченията си като клиентска реализация. С нарастването на сложността на слоя Habitat и броя на услугите на OpenAI промените в протокола с обратна съвместимост станаха неосъществими.

В един случай искахме да ограничим обхвата на последствията от прекъсване в отделен регион за най-критичните ни набори от данни, като ги мигрираме към набор от регионално разпределени акаунти в Azure Cosmos DB. Тази промяна изискваше да добавим допълнителна логика за маршрутизиране в клиента, изключена чрез функционален флаг, да осигурим внедряването ѝ при всички клиенти и след това да включим флага.

Координирането на внедряванията в десетки услуги и работата с всеки екип отнеха дни. Преди да активираме промяната, осъзнахме, че искаме да добавим дублиране на трафика, за да проверим логиката за разделяне на дялове. Внедряването му отне още няколко дни. А поправката на грешка в нещо, което се оказа неправилно? Още няколко дни. Накрая бяхме готови да включим флага, но един от екипите върна услугата си по несвързани причини към по-стара версия на клиента с грешка и причини точно прекъсването, което толкова усилено се опитвахме да избегнем.

Промените в клиентската библиотека изискваха сложна координация между десетки услуги — процес, който ставаше все по-неустойчив, неефективен и податлив на оперативни проблеми. За да ограничим това оперативно разклоняване при бъдещите внедрявания, решихме да превърнем Habitat в самостоятелна услуга.

Като отделихме логиката за съхранение в самостоятелна услуга, създадохме единна точка за контрол на внедряванията, наблюдаемостта и подобренията на платформата. Вместо да управляваме разпокъсани актуализации, можехме да прилагаме подобренията централизирано и така всеки продукт на OpenAI да се възползва незабавно.

Централизираната услуга ни дава и единна контролна точка за прилагане на най-надеждните механизми за сигурност и поверителност на данните. В услугата Habitat можем централизирано да налагаме политики за контрол на достъпа, да водим одитни журнали и да ограничаваме достъпа до основните ресурси за съхранение като Azure Cosmos DB. Habitat играе критична роля в защитата на потребителските данни и предотвратяването на неупълномощен достъп от външни, вътрешни и Агентни участници.

Стартиране на Python услуга в голям мащаб

Знаехме, че ни е необходима услуга, но все още не искахме да се отказваме от Python въпреки допълнителните разходи при използването му за услуга. Използването на Python за услуга с висока производителност увеличи мрежовото закъснение и доведе до значителни разходи за мащабиране на CPU и паметта в сравнение с локалното изпълнение на библиотеката. Освен това осъзнавахме, че неефективността на Python няма да е приемлива при 100-кратен мащаб, което правеше бъдещото пренаписване почти сигурно.

Ние обаче разглеждахме това като стратегически поет технически дълг. Тогава основната ни цел не беше оптимизирането на разходите или ресурсите, а да премахнем пречките пред продуктовите разработчици и да постигнем стабилност на платформата. Като приехме краткосрочните компромиси с производителността на Python услугата, можехме да дадем приоритет на по-неотложните предизвикателства, да установим основните си API и да изградим надеждна инфраструктура.

Направихме и премерен залог, че бързият напредък на собствените ни модели за програмиране ще улесни техническия път в бъдеще. Заложихме, че когато стане необходима пълна миграция от Python, Codex и GPT ще я направят осъществима. В крайна сметка този залог се оказа правилен.

Работата на Habitat като Python услуга щеше да е неоптимална от гледна точка на производителността, но беше необходим избор. Python ни позволява да се движим бързо, но това не означава, че можехме да пренебрегнем предпазливостта и да приемем осезаемо по-големи закъснения. Когато средната потребителска заявка води до стотици обръщения към базата данни, потребителят усеща най-бавното от тях. Установихме, че основното предизвикателство при работа на Python услуга в такъв мащаб е управлението на крайните закъснения.

Проследяване на забавянето в asyncio

Asyncio помага на Python да изпълнява едновременно натоварвания, зависими от входно-изходни операции, но не заобикаля Python GIL и не осигурява паралелизъм на CPU. Освен проксирането на заявки с много входно-изходни операции Habitat изпълнява редица задачи, натоварващи CPU, и фонови задачи: маршрутизиране, компресиране, шифроване, изчисляване на контролни суми, проверки на изправността на зависимите услуги, дублиране и хеджиране на заявки.

При толкова много натоварващи CPU и фонови задачи в услугата забавянето при планиране от asyncio лесно може да стане основен фактор за крайното закъснение на заявките. Преди настройването за първоначалното пускане на услугата видяхме в следите на заявки със закъснение p99 и по-високо, че макар зависимото хранилище да отговаря бързо, заявките често блокират, докато отговорната корутина чака да бъде планирана отново, за да анализира отговора.

Фигура 03 · Проследяване на забавянето в asyncio

Едновременността не е паралелизъм на CPU

Asyncio в Python позволява едновременна обработка на заявки, но във всеки момент в нишката на CPU се изпълнява само една заявка. Това оказва значително влияние върху закъсненията на заявките, когато CPU трябва да извърши много работа.

Обработка на заявка/отговор от CPUМрежово четене/запис в PythonИзчакване на Cosmos

Ниско натоварване на CPU

Кратки стъпки в Python; изчакванията на I/O се застъпват

Високо натоварване на CPU

Дългите стъпки в Python карат готовите отговори да чакат

0.0 / 40 примерни единици

За Python услугите в OpenAI установихме, че освен стандартните показатели за използване и насищане на паметта, CPU, мрежата и диска е изключително важно да наблюдаваме цикъла на asyncio и натоварването му, след което да настройваме системата съответно.

Като планираме периодично фонови задачи и записваме разликата между очаквания и действителния момент на изпълнение, можем емпирично да измерваме в реално време забавянето при планиране в цикъла за събития. При високо натоварване и много скъпи задачи дори умерен брой едновременни заявки на процес е достатъчен, за да предизвика значителни колебания в планирането — до стотици милисекунди, а в някои крайни случаи и няколко секунди.

Затова ограничаваме всеки процес да обслужва само малък брой едновременни заявки и вместо това мащабираме значително броя на работните Python процеси.

Намаляване на крайното закъснение в конфигурациите на функционалните флагове

При първоначалното пускане на услугата чрез профилиране на CPU в реална среда открихме една от основните причини за голямото забавяне в asyncio и произтичащите крайни закъснения: периодичното анализиране на JSON конфигурациите на функционалните ни флагове чрез Statsig — инструмент за управление на функционални флагове, A/B тестове и други.

По подразбиране Statsig проверяваше за обновени конфигурации всяка минута, без случайно отклонение, а конфигурацията включваше всички производствени правила за всяка услуга. Отделно беше взето архитектурно решение във всеки pod да работят до 8 Python процеса, за да се постигнат по-високо използване на CPU и по-ниски закъснения. В резултат всяка минута настъпваше момент, когато всички работни процеси във всеки pod спираха обработката на текущите заявки и използваха циклите на CPU за анализ на огромен конфигурационен файл.

След като профилирането на CPU ни помогна да установим първопричината, решението беше лесно: внедрихме по-малка целева конфигурация, удължихме интервала за обновяване и добавихме случайно отклонение към подобни фонови задачи.

Балансиране на натоварването и управление на пуловете от връзки

За да поддържаме ниско забавяне в asyncio, е изключително важно да разпределяме добре заявките между сървърните процеси; без подходящи настройки обединяването на връзки може да работи срещу тази цел.

При обединяване на връзки от страна на клиента един клиентски процес, който изпраща много едновременни заявки, може да установи само няколко сървърни връзки и така да насочи цялото си натоварване само към няколко процеса. Преди да коригираме балансирането на натоварването, използването на услугата ни варираше значително, като някои крайни процеси обслужваха 5–10 пъти повече едновременни заявки от средното.

Открихме това при случаен инцидент, когато въпреки спирането на клиента, претоварващ част от услугата ни, част от процесите останаха влошени дълго след пиковия трафик. Всъщност забелязахме неконтролируемо влошаване на тези процеси — те получаваха все повече заявки, докато не ги рестартирахме. След като даден pod се претовареше, определено поведение насочваше към него още повече трафик. Това беше клас проблеми, който някои наши колеги познаваха добре от предишна работа: метастабилен отказ(отваря се в нов прозорец).

Подозирахме пула от връзки и проверихме предположението, като ограничихме максималната продължителност на повторното използване на връзките. Това действително ограничи влошаването и потвърди посоката на разследването ни. Допълнителното разследване установи, че TCPConnector на aiohttp в Python по подразбиране използва повторно връзките по LIFO: за следващата заявка се избира най-скоро върнатата връзка. Обикновено това е разумна настройка: повторното използване на скорошни връзки позволява допълнителните връзки, създадени за пиков трафик, да изтекат при неактивност и намалява разходите за поддържането им. В нашия случай това предизвика метастабилен отказ. При пик на заявките връзките към по-бавните претоварени сървъри се връщаха в пула по-късно и затова се избираха по-често за следващите заявки, което постепенно концентрираше още трафик върху вече затруднените pod-ове. Промяната на пула така, че да използва повторно връзките по FIFO, прекъсна тази обратна връзка и дори намали вариацията в заявките при стабилно състояние.

Фигура 04A · Обединяване на връзки от страна на клиента

LIFO връща новата работа към бавния процес

След пик на заявките по-бавните сървъри връщат връзките в пула последни. LIFO насърчава натрупването на повече работа върху същите по-бавни сървъри.

Първоначален пик достига до A, B и по-бавния процес C.

Фигура 04B · Обединяване на връзки от страна на клиента

FIFO прекъсва обратната връзка при повторното използване на връзки

FIFO поддържа повече активни връзки след пик, но разпределя натоварването справедливо между всички сървъри.

Първоначален пик достига до A, B и по-бавния процес C.

Днес разчитаме основно на Istio и Envoy за обединяване на връзките и по-добри стратегии за балансиране, съобразени с натоварването на сървърите, в цялата инфраструктура на OpenAI, като така избягваме проблема изцяло.

Предотвратяване на претоварването на зависимите ресурси

Страничен ефект от настройването за ниско забавяне в asyncio и наличието на толкова много Python процеси е, че огромният брой връзки може много лесно да претовари зависимите системи — явление, известно като „гръмотевично стадо“.

Обикновено ежедневно внедряване — ако не е настроено да протича бавно — може да предизвика значително натоварване на CPU от непрекъснатото създаване и затваряне на връзки. А изтичане на връзки може да изведе мрежата от строя чрез насищане на NAT шлюза. Тези проблеми не са необичайни и за други услуги, но прагът за възникването им е значително по-нисък при десетократно повече процеси. Често се насищат мрежови ресурси, за които клиентите не очакват, че трябва да са подготвени в стабилно състояние, ако се ръководят единствено от производителността.

Разчитаме на Envoy и за максимално концентриране на връзките. Използваме го, за да надграждаме HTTP/1 връзките на Python до HTTP/2 и да се възползваме от мултиплексирането, след което обединяваме тези връзки и удължаваме живота им. Envoy ни осигурява и централизирано място за въвеждане на ограничения на честотата и прекъсвачи на веригата, които биха били по-малко ефективни във всеки самостоятелен Python процес.

Фигура 05 · Концентриране на връзките

Същите заявки, по-малко връзки

Обединяването на връзки и мултиплексирането на HTTP/2 връзки помагат да се намали натоварването от връзки върху зависимите системи.

ЗаявкаОтговорНеактивна постоянна връзка

Защо Habitat прави по-малко

Една от причините да мащабираме 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 към Rust

Отлагането на пренаписването на Python с една година ни позволи да се съсредоточим върху по-неотложни и значими предизвикателства в периода на свръхрастеж. Със съзряването на платформата и продължаващото ускоряване на растежа ни — при положение че бяхме втората по брой ядра услуга в OpenAI и четвърта по мащаб на Envoy — най-после беше време да оставим Python зад гърба си. В пиковия си период Python ни помогна да обслужваме над 20 милиона заявки в секунда.

През второто тримесечие на 2026 г. само с двама инженери, Codex и GPT‑5.5 успяхме да пренапишем цялата услуга на Rust. Новата Rust услуга вече обработва 95% от продукционните ни заявки; през следващите седмици ще изведем Python изцяло от употреба. Данните ни показват, че Rust услугата е 6 пъти по-ефективна по отношение на CPU и 15 пъти по-ефективна по отношение на паметта от версията на Python, със значително по-ниски средни и крайни закъснения. Планираме да споделим още научени уроци в бъдеща публикация.

Оптимизиране на слоя на базата данни — Azure Cosmos DB

Услугата на Python — а вече и на Rust — е само един аспект на Habitat. Във втората част от тази поредица за бързото мащабиране на онлайн хранилището ни за над 1 милиард потребители на ChatGPT ще разгледаме слоя за съхранение и как Habitat обслужва над 500 петабайта и повече от 70 милиона заявки в секунда.

Ако искате да работите по OLTP системи в авангарден мащаб и се интересувате от този тип инженерна дейност, разгледайте тази свободна позиция в екипа ни.

Автори

Jon Lee, Chaomin Yu и Ben Ries