Переход к основному контенту
OpenAI

11 сентября 2026 г.

Инженерия

Быстрое масштабирование хранилища для более 1 млрд пользователей ChatGPT

Как мы адаптировали платформу хранения приложений Habitat на Python к беспрецедентному росту.

Авторы: Джон Ли, Чаомин Ю и Бен Рис, технические специалисты

Загрузка…

Каждый продукт OpenAI зависит от быстрого и надежного доступа к данным — при входе пользователя в систему, проверке настроек Codex или начале нового разговора в ChatGPT. Прежде чем продукт сможет ответить, каждое такое действие может потребовать множества отдельных операций поиска данных. Если эти запросы выполняются медленно, продукт кажется медленным. Если эти запросы завершаются с ошибкой, продукт полностью перестает работать.

Habitat — созданная нами платформа оперативного хранения, которая обеспечивает продуктам OpenAI быстрый и надежный доступ к необходимой информации. Сейчас Habitat обрабатывает более 70 миллионов запросов в секунду и поддерживает продукты, которыми еженедельно пользуются свыше миллиарда человек почти в 40 географических регионах. Habitat впервые запустили для поддержки пользовательские GPT на DevDay 2023 как простую клиентскую библиотеку на Python, подключенную к одной базе данных. Сегодня это сложная распределенная система, обслуживающая более 500 петабайт данных.

Рисунок 01 · Что такое Habitat?

Платформа оперативного хранения

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

  • Запрос
  • Ответ
  • Изменения (CDC)

Клиенты

Платформа оперативного хранения

Ресурсы хранения

  • ChatGPT
  • API
  • Codex
  • Внутренние сервисы
  • И многое другое

Habitat

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

Создавать и эксплуатировать инфраструктуру такого масштаба непросто, но и не особенно сложно. Уникальность нашей ситуации заключалась в беспрецедентной скорости масштабирования: нам приходилось одновременно поддерживать колоссальный рост числа пользователей и спроса на продукты, а также создавать зрелую платформу. Системные инженеры часто закладывают десятикратное масштабирование и надеются, что его хватит на несколько лет, пока они готовятся к следующему десятикратному росту. В нашем случае последние три года мы ежегодно росли более чем в десять раз. Поэтому создание и эксплуатация Habitat превратились в череду тактических решений с тщательно выбранной последовательностью: мы изучали каждый компонент на самом низком уровне, чтобы выжать максимум из существующего стека, и одновременно преодолевали дефицит ресурсов хранения и вычислений, выигрывая время для фундаментальных инвестиций.

  • 70 млн+

    запросов в секунду

  • 1 млрд+

    человек в неделю

  • 500 ПБ+

    данных

По мере роста OpenAI рос и Habitat: сначала он стал достаточно надежным для критически важного трафика рабочих систем, затем достаточно быстрым для пользователей по всему миру и наконец научился эффективно работать в огромном масштабе. Это первая публикация из двухчастной серии о масштабировании нашего оперативного хранилища. Здесь мы расскажем, как развивался Habitat, почему мы превратили библиотеку в сервис и как сделали сервис на необычном для серверного стека языке Python надежным уровнем платформы хранения.

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

Что такое Habitat?

В основе Habitat лежала простая идея: разработчики продуктов не должны заниматься управлением базами данных. Habitat впервые запустили для поддержки пользовательских GPT на 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 хорошо работала, и разработчики продуктов OpenAI быстро внедряли Habitat, хотя централизованной инициативы по отказу от самостоятельно обслуживаемых Postgres и Azure Cosmos DB не было.

По мере развития потребностей продуктов разработчикам было несложно добавлять в общую библиотеку поддержку клиентского кеширования, сжатия или шифрования.

Создание сервиса для более эффективной поддержки нескольких сложных продуктов

К середине 2025 года Habitat достиг пределов клиентской реализации. По мере усложнения уровня Habitat и роста числа сервисов OpenAI обратно совместимые изменения протокола стали практически невозможны.

Однажды мы решили снизить последствия сбоя в любом отдельном регионе для самых критичных наборов данных, перенеся их в ряд регионально распределенных учетных записей Azure Cosmos DB. Для этого требовалось добавить в клиент дополнительную логику маршрутизации, отключенную флагом функции, развернуть ее у всех клиентов, а затем включить флаг.

Координация развертывания в десятках сервисов и работа с каждой командой заняли несколько дней. Перед включением мы решили добавить теневое выполнение запросов, чтобы проверить правильность логики шардирования. На его развертывание ушло еще несколько дней. Исправить обнаруженную ошибку? Еще несколько дней. Наконец мы были готовы включить флаг, но одна из команд по несвязанным причинам откатила свой сервис к прежней версии клиента с ошибкой, что вызвало именно тот сбой, которого мы так старались избежать.

Изменения клиентской библиотеки требовали сложной координации десятков сервисов, и этот процесс становился все более хрупким, неэффективным и подверженным эксплуатационным сбоям. Чтобы в будущем сократить масштаб операционной координации при развертывании, мы решили выделить Habitat в отдельный сервис.

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

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

Запуск масштабируемого сервиса на Python

Мы понимали, что нам нужен сервис, но пока не хотели отказываться от Python, несмотря на дополнительные накладные расходы при его использовании для сервиса. Использование Python для сервиса с высокой пропускной способностью увеличило сетевую задержку и существенно повысило затраты CPU и памяти при масштабировании по сравнению с локальным выполнением библиотеки. Кроме того, мы понимали, что при стократном масштабе неэффективность Python станет неприемлемой, поэтому последующее переписывание сервиса было почти неизбежно.

Однако мы рассматривали это как осознанное принятие технического долга. На тот момент нашей главной целью была не оптимизация затрат или ресурсов, а устранение препятствий для разработчиков продуктов и обеспечение стабильности платформы. Временно согласившись на компромиссы в производительности сервиса на Python, мы смогли сосредоточиться на более насущных задачах, сформировать основные API и создать надежную инфраструктуру.

Мы также сделали обдуманную ставку на то, что быстрое развитие наших моделей для программирования в будущем упростит техническую сторону задачи. Мы рассчитывали, что к моменту полного отказа от Python Codex и GPT сделают такую миграцию осуществимой. В итоге эта ставка оправдалась.

Запуск Habitat как сервиса на Python был не лучшим решением с точки зрения производительности, но необходимым. Python позволяет нам быстро двигаться вперед, но это не значит, что мы могли забыть об осторожности и смириться со значительно более высокими задержками. Если средний пользовательский запрос приводит к сотням обращений к базе данных, пользователь ощущает задержку самого медленного из них. Мы выяснили, что главная сложность эксплуатации сервиса на Python в таком масштабе — управление хвостовыми задержками.

Отслеживание задержки asyncio

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

Из-за большого числа ресурсоемких для CPU операций и фоновых задач задержка планирования asyncio в нашем сервисе легко может стать главным источником хвостовой задержки запросов. До оптимизации перед первым запуском сервиса трассировки запросов с задержкой p99 и выше показывали: нижестоящее хранилище отвечало быстро, но запросы часто останавливались в ожидании, пока ответственная корутина снова получит процессорное время и обработает ответ.

Рисунок 03 · Отслеживание задержки asyncio

Конкурентность — не параллельное выполнение на CPU

Asyncio в Python позволяет обрабатывать запросы конкурентно, но в каждый момент времени в потоке CPU выполняется только один запрос. При большом объеме вычислений на CPU это существенно увеличивает задержку запросов.

Обработка запросов и ответов на CPUСетевое чтение и запись PythonОжидание Cosmos

Низкая нагрузка на CPU

Краткие этапы Python; ожидания ввода-вывода перекрываются

Высокая нагрузка на CPU

Долгие этапы Python задерживают готовые ответы

0.0 / 40 условных единиц

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

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

Поэтому каждый процесс обслуживает лишь небольшое число одновременных запросов, а вместо этого мы значительно наращиваем количество рабочих процессов Python.

Снижение хвостовой задержки в конфигурациях флагов функций

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

По умолчанию Statsig каждую минуту без случайного смещения запрашивал обновленные конфигурации, включавшие все рабочие правила всех сервисов. Кроме того, ранее было принято архитектурное решение запускать до восьми процессов Python в каждом поде, чтобы повысить загрузку CPU и снизить задержки. В совокупности это означало, что каждую минуту наступал момент, когда все рабочие процессы каждого пода приостанавливали обработку текущих запросов и тратили ресурсы CPU на разбор огромного файла конфигурации.

После того как профилирование CPU помогло найти первопричину, исправление оказалось простым: развернуть более компактную целевую конфигурацию, увеличить интервал обновления и добавить случайное смещение для подобных фоновых задач.

Балансировка нагрузки и управление пулами подключений

Чтобы задержка asyncio оставалась низкой, также крайне важно равномерно распределять запросы между серверными процессами; без должной настройки пулы подключений могут этому мешать.

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

Мы случайно обнаружили это во время инцидента: хотя клиент, перегружавший часть нашего сервиса, был остановлен, состояние ряда процессов оставалось ухудшенным еще долго после всплеска трафика. Более того, состояние этих процессов ухудшалось лавинообразно: они получали все больше запросов, пока мы их не перезапустили. После перегрузки пода некий механизм продолжал направлять на него все больше трафика. Некоторые наши коллеги хорошо знали этот класс сбоев по предыдущей работе: метастабильный сбой(открывается в новом окне).

Мы заподозрили пул подключений и проверили гипотезу, ограничив максимальное время повторного использования подключения. Это действительно сдержало ухудшение и подтвердило направление расследования. Дальнейшее расследование показало, что TCPConnector библиотеки aiohttp в Python по умолчанию повторно использует подключения по принципу LIFO: для следующего запроса выбирается подключение, вернувшееся последним. Обычно это разумное поведение по умолчанию: повторное использование недавних подключений позволяет дополнительным подключениям, созданным для всплеска трафика, закрыться по тайм-ауту бездействия и снижает затраты на их поддержку. Но в нашем случае это вызвало метастабильный сбой. Во время всплеска запросов медленные перегруженные серверы позже возвращали подключения в пул, поэтому последующие запросы чаще выбирали именно их, постепенно направляя все больше трафика на уже испытывающие трудности поды. Изменение пула для повторного использования подключений по FIFO разорвало этот цикл обратной связи и даже снизило разброс числа запросов в стабильном состоянии.

Рисунок 04A · Клиентский пул подключений

LIFO возвращает новую работу медленному процессу

После всплеска запросов более медленные серверы последними возвращают подключения в пул. LIFO способствует концентрации дополнительной работы на тех же медленных серверах.

Первоначальный всплеск достигает A, B и более медленного процесса C.

Рисунок 04B · Клиентский пул подключений

FIFO разрывает цикл обратной связи при повторном использовании подключений

После всплеска FIFO сохраняет больше активных подключений, но равномерно распределяет нагрузку между всеми серверами.

Первоначальный всплеск достигает A, B и более медленного процесса C.

Сегодня во всей инфраструктуре OpenAI мы в основном используем Istio и Envoy для организации пулов подключений и более эффективной балансировки с учетом нагрузки серверов, что позволяет полностью избежать этой проблемы.

Предотвращение перегрузки нижестоящих ресурсов

Побочный эффект оптимизации для низкой задержки asyncio и огромного числа процессов Python — нижестоящие зависимости легко перегрузить множеством подключений. Это явление называют «лавиной запросов».

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

Мы также используем Envoy для максимальной консолидации подключений. С его помощью мы преобразуем подключения HTTP/1 из Python в HTTP/2, чтобы использовать мультиплексирование, а затем объединяем эти подключения в пул и продлеваем срок их существования. Envoy также предоставляет единую точку для реализации ограничений частоты запросов и механизмов автоматического прерывания запросов, которые были бы менее эффективны в каждом отдельном процессе Python.

Рисунок 05 · Консолидация подключений

Те же запросы, меньше подключений

Пулы подключений и мультиплексирование HTTP/2 помогают снизить нагрузку подключений на нижестоящие системы.

ЗапросОтветНеактивное keep-alive-подключение

Почему 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 в шесть раз эффективнее использует CPU и в 15 раз эффективнее расходует память, чем версия на Python, а его средние и хвостовые задержки значительно ниже. В будущем мы планируем поделиться дополнительными выводами в блоге.

Оптимизация уровня базы данных Azure Cosmos DB

Сервис на Python, а теперь на Rust, — лишь одна из составляющих Habitat. Во второй части серии о том, как мы быстро масштабировали оперативное хранилище для более чем миллиарда пользователей ChatGPT, мы расскажем об уровне хранения и о том, как Habitat обслуживает свыше 500 петабайт данных и более 70 миллионов запросов в секунду.

Если вам интересно заниматься OLTP-системами передового масштаба и решать подобные инженерные задачи, ознакомьтесь с открытой вакансией в нашей команде.

Автора

Jon Lee, Chaomin Yu, Ben Ries