OpenAI

23 жовтня 2026 р.

Інженерія

Стрімке масштабування онлайн-сховища для понад 1 млрд користувачів ChatGPT (частина II)

Як ми оптимізували Azure Cosmos DB у нашій платформі зберігання даних застосунків Habitat, щоб упоратися з безпрецедентним зростанням.

Автори: Джон Лі, Грач’я Акопян і Чаомінь Юй, співробітники технічної команди

Завантаження…

Усім продуктам OpenAI потрібен швидкий і надійний доступ до даних, який забезпечує наша платформа зберігання Habitat. Вона має відповідати за мілісекунди понад 1 мільярду користувачів у 40 географічних регіонах. Перед нашою інфраструктурою постало надзвичайно складне завдання: підтримувати стрімке зростання й нові сценарії використання, водночас підвищуючи надійність, продуктивність і швидкість роботи розробників продуктів. Для цього довелося переосмислити архітектуру й експлуатацію нашої платформи онлайн-зберігання. Ми постійно зважували компроміси, дотримуючись такої послідовності: спершу забезпечити достатню надійність для критично важливого продуктового трафіку, потім — достатню швидкість для користувачів у всьому світі й, нарешті, налагодити ефективну роботу у величезному масштабі.

У цій серії з двох частин ми розповідаємо, як перетворили Habitat із простої клієнтської бібліотеки й бази даних на глобально розподілену платформу зберігання, що обслуговує понад 500 петабайтів даних. Частина I була присвячена перетворенню Habitat із клієнта на Python на сервіс. У ній також ішлося про методи, які дали нам змогу розширити можливості сервісу на Python далеко за межі того, що багато хто вважав би практично доцільним.

У цій публікації, частині II, ми розглянемо, як масштабували базовий компонент зберігання — Azure Cosmos DB. Завдяки тісній співпраці з командою Azure ми знайшли дієвий підхід до багатотенантності на основі спільно керованих контейнерів, що забезпечує чудову продуктивність читання у величезному глобальному масштабі.

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

Платформа оперативного зберігання

Habitat — створена нами платформа оперативного зберігання, що забезпечує продуктам OpenAI швидкий і надійний доступ до потрібної інформації.

  • Запит
  • Відповідь
  • Зміни (CDC)

Клієнти

Платформа оперативного зберігання

Ресурси зберігання

  • ChatGPT
  • API
  • Codex
  • Внутрішні служби
  • Та інше

Habitat

  • КешуванняКеші
  • Політики ACLАвторизація
  • Розміщення та локалізація данихВимоги до локалізації даних
  • ШифруванняБезпека даних
  • ІзоляціяМультитенантність
  • Обмеження частотиФормування запитів
  • МаршрутизаціяПошук схеми · Локалізація даних
  • Azure Cosmos DBОперативне сховище
  • NanobaseОперативне сховище
  • ValkeyКеші
  • Сховище BLOB-об’єктівРесурси зберігання
Служби CDCФіксація змін даних
  • Databricks
  • Rockset
  • Kafka
  • Та інше

Надійна багатотенантність у великому масштабі

Зі зростанням компаній інфраструктурні команди часто переходять від однотенантних систем до багатотенантних. За однотенантності кожна команда, що відповідає за певну частину продукту, підтримує власну систему. Це звужує зону впливу збоїв, спрощує розмежування відповідальності та забезпечує ізоляцію навантажень. Зі зростанням команд і кількості частин продуктів така експлуатація стає дорогою. За однотенантності кожна продуктова команда відповідає за планування ресурсів, що часто призводить до їх значного надлишкового виділення.

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

Працюючи над Habitat, ми мали зважити всі ці компроміси, щоб створити надійну й ефективну систему зберігання великого масштабу. Сьогодні Habitat — це багатотенантний шар бази даних для багатьох продуктів OpenAI. Але ми пройшли повне коло: від одного багатотенантного контейнера Azure Cosmos DB через окремі однотенантні контейнери зберігання до повернення до багатотенантного контейнера за замовчуванням. Ми ще на початку розвитку багатотенантності в Habitat: підтримуємо багато сценаріїв використання, але досі могли відкладати інвестиції в цей напрям, де можливо використовуючи вбудовані примітиви Azure Cosmos DB.

Короткий вступ до контейнерів Azure Cosmos DB

Перш ніж розповісти про наш шлях з Azure Cosmos DB, наведемо основні відомості:

  • Обліковий запис Azure Cosmos DB визначає набір контейнерів і політику реплікації

  • Кожному контейнеру виділяється певна пропускна здатність в одиницях запитів за секунду (RU/s)

  • Дані в кожному контейнері зберігаються з типовим шардуванням за заданим ключем логічного розділу, із задокументованими лімітами обсягу сховища й пропускної здатності для кожного такого ключа

  • Azure Cosmos DB розподіляє ключі логічних розділів між меншою кількістю фізичних розділів. Фізичні розділи діляться на кілька нових, коли обсяг даних перевищує поріг або контейнеру потрібно більше фізичних розділів для підтримання виділеної пропускної здатності

Етап I: покладаємося на примітиви Azure Cosmos DB

Спочатку ми пропускали будь-яке клієнтське навантаження, покладаючись на заявлений ліміт 10 тис. RU/s на ключ логічного розділу як механізм зворотного тиску. На початку ми також використовували лише один контейнер Azure Cosmos DB за замовчуванням у кожному обліковому записі. Це працювало досить добре, але виявилося проблемним із кількох причин:

Ліміти ключів логічних розділів

Через ранні рішення щодо API ми надали клієнтам можливість безпосередньо вибирати ключ логічного розділу. Унаслідок цього в різних продуктових сценаріях часто виникають колізії поширених ключів розділів, як-от user_id або workspace_id. Оскільки ці сценарії ділили ліміти Azure Cosmos DB для тих самих ключів логічних розділів, така архітектура обмежувала загальну пропускну здатність для окремого користувача.

До переходу на Habitat і Azure Cosmos DB однією з типових проблем масштабування Postgres було те, що численні запити від організації чи ключа з дуже високою активністю — одного тенанта, який створював непропорційно велике навантаження, — могли вивести з ладу всю базу даних. Ми доклали значних спільних зусиль, щоб кешувати такі ключі та впровадити механізм оренди під час промахів кешу, аби спричинене ними навантаження не перевантажувало базову базу даних.

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—

Шумні сусіди

Хоча задокументовані ліміти обсягу даних і пропускної здатності стосуються ключів логічних розділів, фактично обмеження застосовуються на рівні фізичного розділу. На практиці це означає, що логічні розділи не можуть досягти 10 000 RU/s. Натомість вони ділять ліміти фізичного розділу з усіма іншими ключами логічних розділів, розміщеними в ньому.

Через це шумні сусіди впливали на багато не пов’язаних між собою ключів логічних розділів: навантаження, що працювали з даними вузькоспеціалізованих функцій продукту, порушували основні процеси входу та реєстрації.

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—

Слабкі розділи

Ліміт пропускної здатності окремого фізичного розділу також змінюється залежно від загальної пропускної здатності, виділеної контейнеру Azure Cosmos DB. Виділена контейнеру пропускна здатність розподіляється приблизно порівну між його фізичними розділами.

Зі зростанням обсягу даних фізичні розділи діляться, тож їхня загальна кількість збільшується, а загальна виділена пропускна здатність залишається незмінною. У результаті зі зростанням обсягу даних фактичний ліміт пропускної здатності кожного розділу зменшується.

У сценаріях, де ми зберігаємо найбільші обсяги даних, подібних до BLOB-об’єктів, це створює ризик збою: саме лише зростання обсягу сховища знижує пропускну здатність для активних навантажень, навіть якщо частота запитів і використання залишаються стабільними.

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

Етап II: спроба ізоляції навантажень і однотенантності

Окремі контейнери допомагають частково розв’язати проблеми лімітів ключів розділів і шумних сусідів. Кожному окремому контейнеру можна виділити власні незалежні фізичні розділи. Тоді шумними сусідами чи джерелами перетинів у просторі ключів розділів можуть бути лише різні навантаження всередині самого контейнера. Водночас створення нових контейнерів потребує додаткових зусиль: для кожного треба окремо планувати ресурси. Тому ми прагнемо створювати контейнери лише там, де це виправдано межами сервісу або сценарію використання.

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

Однак ми починали з контейнера за замовчуванням, тож багато давніших критично важливих сценаріїв, на жаль, залишалися прив’язаними до нього без міграції даних. Щоб захистити критично важливі сервіси, які досі покладалися на дані в спільному контейнері за замовчуванням, ми часто радили командам створювати окремі контейнери для нових сервісів або великих функцій продуктів. У міру масштабування навантаження на контейнер за замовчуванням зростало, як і кількість інцидентів у робочому середовищі. Ми почали створювати контейнери для кожного нового сервісу чи великої функції продукту, аби лише захистити контейнер за замовчуванням від додаткового навантаження.

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

Відсутність стабільного сукупного зростання

У старому спільному контейнері за замовчуванням зростання окремого нового сценарію від 0 до 1 млн QPS навряд чи суттєво змінювало загальне сукупне використання. Натомість в ізольованому контейнері зростання нового сценарію від 0 до 1 млн QPS могло означати навантаження в 1000 разів більше за базове, яке створювало лише внутрішнє використання продукту працівниками.

З виділеними контейнерами командам тепер потрібно було пам’ятати про завчасне виділення пропускної здатності, очікуваної на момент запуску. Продуктові команди часто випускали функції в робоче середовище й забували заздалегідь масштабувати ресурси. Тож у день запуску ми опинялися на нарадах із реагування на критичні інциденти, намагаючись в останню мить збільшити ресурси контейнерів.

Саме це є ключовою перевагою змішування навантажень у багатотенантних системах, яку ми втрачаємо за такої стратегії контейнерів заради кращої ізоляції.

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

Планування ресурсів

З часом моніторинг використання виділених контейнерів також почав вимагати глибокого знання продукту: коли трафік зміниться або зросте.

Ми можемо надати простий скрипт площини керування, який збільшує виділену пропускну здатність кожного контейнера відповідно до тенденцій зростання. Але без стабільного сукупного зростання правильне масштабування фактично потребувало участі кожної продуктової команди OpenAI в плануванні ресурсів.

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

Етап III: багатотенантність за замовчуванням із можливістю переміщення даних

Зі зростанням організації ці експлуатаційні проблеми дедалі більше заважали масштабуванню. Відсутність єдиної централізованої команди планування призвела до того, що багато команд планували неякісно. Зрештою ми повернулися до багатотенантного рішення й у тісній співпраці з командою Azure усунули початкові проблеми багатотенантності в архітектурі зі спільними ресурсами:

Обмеження запитів до гарячих ключів

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

Якість обслуговування (QoS)

QoS із розподілом запитів за рівнями так само не дає фоновим навантаженням, як-от масові вставки чи вивантаження даних, використати всю пропускну здатність фізичного розділу. Ми призначаємо запитам цих навантажень нижчий пріоритет, тому вони обмежуються першими. Це захищає від обмежень більш пріоритетні інтерактивні запити, які обслуговують кінцевих користувачів.

Безсерверний режим

В Azure Cosmos DB уже був безсерверний режим, який міг розв’язати нашу проблему слабких розділів у режимі з виділеною пропускною здатністю. Однак він мав суттєвий недолік: масштабувався лише за обсягом зайнятого сховища й обмежував використання RU до 5 тис. RU/s на фізичний розділ. Це розв’язало б проблему слабких розділів, але не дало б масштабувати сценарії з високим споживанням RU.

Команда Azure Cosmos DB створила для нас удосконалений безсерверний режим: кожен фізичний розділ міг масштабуватися до 10 тис. RU/s, а поділ за обсягом сховища доповнився поділом за споживанням RU. Завдяки цьому ми перестали вручну відстежувати й масштабувати контейнери.

Ці зміни дали змогу повернутися до одного спільного контейнера. Це значно спростило для продуктових команд як попереднє, так і поточне планування ресурсів, зберігши ізоляцію навантажень. За місяці, що минули відтоді, у нас не було жодного інциденту через виділення ресурсів або шумних сусідів, попри прискорення розробки продуктів.

Вища надійність завдяки спільному керуванню сервісами

Коли компанії досягають масштабу OpenAI, керовані сервіси стають менш «керованими». Багато навантажень виходять за типові межі інфраструктури хмарного провайдера. Коли OpenAI стала одним із найбільших користувачів Azure Cosmos DB, для успішної експлуатації знадобився інший підхід: спільні тести й панелі моніторингу, прямі канали зв’язку між інженерами та спільна відповідальність за збої, що виникають лише в нашому масштабі. Сьогодні наш найбільший обліковий запис Azure Cosmos DB зберігає десятки петабайтів даних і обслуговує понад 20 млн QPS. Наскільки нам відомо, ми — єдина компанія, що розгорнула Azure Cosmos DB у такому масштабі.

Наприкінці 2024 року регіональний збій наочно показав, чому ця співпраця необхідна. Тоді відключення електроенергії сталося в основному регіоні Azure одного з наших найбільших облікових записів Azure Cosmos DB. Під час аварійного перемикання ми з’ясували, що перехід наших найбільших облікових записів на вторинний регіон займе кілька годин. Ні наша команда, ні команда Azure Cosmos DB не тестували це в нашому масштабі.

Приблизно за місяць, повертаючи ці облікові записи до початкового регіону, ми спричинили ще один серйозний збій. Лавина підключень до початкового регіону перевантажила його шлюз Azure Cosmos DB. Через особливість обробки аварійних перемикань клієнтом Azure Cosmos DB у режимі шлюзу всі клієнти негайно встановили з’єднання й почали надсилати запити до початкового регіону, хоча туди повернулася лише частина фізичних розділів.

Під час кожного збою OpenAI та Azure застосовували свої процедури реагування на інциденти, виявляли першопричини й упроваджували виправлення. Але ці збої були симптомами ширшої системної проблеми в тому, як наша команда й команда Azure Cosmos DB організовували роботу та тестування. Спочатку керовані сервіси давали нам змогу рухатися швидко й зосереджуватися на бізнес-цілях. У великому масштабі керовані сервіси стають менш керованими й потребують глибокої взаємодії з постачальником на всіх рівнях — від проєктування до експлуатації.

Сьогодні інженерні команди Habitat і Azure спільно відстежують кожен рівень Habitat — від наших сервісних шарів до фізичних шарів зберігання Azure Cosmos DB. Ми експлуатуємо й тестуємо зміни на обліковому записі Azure Cosmos DB, який має розмір робочого середовища, але не обслуговує його. Ми разом тестуємо й удосконалюємо SDK та визначаємо найкращі практики масштабування й вибору обсягу ресурсів для наших облікових записів Azure Cosmos DB. Наші інженери спілкуються безпосередньо через Teams. Ми навіть надали можливість напряму викликати чергових інженерів одне одного, оминаючи рівні підтримки.

За останній рік ми виконали значну спільну роботу над масштабованістю площини керування та шлюзу Azure Cosmos DB. Додали захист від перевантажень і кешування різних метаданих Azure Cosmos DB у шлюзі, щоб захистити розділ метаданих. Зменшили навантаження від наших процесів habitat-service на Python завдяки пулам з’єднань і частішому їх повторному використанню, розміщували навантаження поруч, де це можливо, та ізолювали критичні навантаження від фонових за допомогою різних VPC.

Такий рівень спільної інженерної роботи був критично важливим для стабільності нашої Azure Cosmos DB протягом останнього року. Будь-яка достатньо велика чи критично важлива система потребує такої командної роботи: подолання бар’єрів між зонами відповідальності та співпраці поза організаційними межами.

Підвищення продуктивності в глобальному масштабі

Як зазначено в частині I, наш основний принцип: спочатку забезпечити роботу, потім прискорити її, а тоді здешевити. Спершу надійність, потім продуктивність, а далі — ефективність. Habitat став критично важливою інфраструктурою для OpenAI, тож першочерговим завданням було забезпечити його надійність. Коли у 2025 році система стабілізувалася, а OpenAI розширила глобальну присутність, наступним обмеженням для користувачів і продуктових команд стала затримка.

Обчислювальні ресурси та сховища часто розташовувалися в різних регіонах, тому міжрегіональні запити були неминучими.

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

Географічне розташування обчислювальних ресурсів і сховищ наведено лише для ілюстрації.

Затримка суттєво різнилася залежно від того, де зберігалися дані й де оброблявся запит. Щоб прискорити запити до Habitat, розробники продуктів додатково кешували дані на боці клієнта, об’єднували запити в пакети, мінімізували читання й записи в базу даних та за можливості виносили роботу за межі критичного шляху. Це дало кілька цікавих продуктових рішень, стійкіших до проблем із базою даних, але водночас ускладнило продукти й сповільнило їх розвиток. Отже, ми не досягли мети Habitat — сприяти швидкій розробці продуктів без потреби розбиратися в базі даних.

У 2026 році це стало одним із головних напрямів нашої роботи. Ми розробили багаторівневу стратегію оптимізації читання, на яке припадає понад 90% запитів Habitat:

Зберігати дані поблизу користувачів, якщо дозволяють ресурси

Для користувачів, на яких поширюються вимоги до локалізації даних, ми маємо низку облікових записів Azure Cosmos DB у різних регіонах Azure по всьому світу. Навіть для користувачів без суворих вимог до локалізації даних розміщення даних поблизу покращує роботу завдяки меншій затримці.

На практиці ми не можемо широко застосовувати це поза сценаріями, де діють вимоги до локалізації даних, адже розміщення обмежене фізичними ресурсами хмари. Через розмір наших наборів даних багато регіонів не мають достатнього обсягу сховища для обслуговування своєї пропорційної частки користувацького трафіку.

У регіонах з обмеженими ресурсами дата-центрів, електроживлення чи охолодження нам іноді доводиться обирати: резервувати ресурси для сховища поруч і знижувати затримку Habitat або використовувати їх для додаткових обчислень з обслуговування запитів, а запити до сховища спрямовувати далі.

Тому рішення про розміщення часто вимагають продуктового компромісу між: А) оптимізацією затримки для різних продуктів і груп користувачів та Б) доступними обсягами сховища й обчислювальних ресурсів.

Широко реплікувати лише найменші й найчутливіші до затримок набори даних

Для навантажень, найчутливіших до затримок, як-от метадані автентифікації, потрібні в кожному запиті, ми зменшуємо час обміну даними (RTT) між обчислювальними ресурсами та Habitat завдяки обліковим записам Azure Cosmos DB із широкою реплікацією в багатьох вторинних регіонах. Деякі облікові записи реплікуються в усі 40 регіонів Azure, де ми обслуговуємо трафік; інші — щонайменше в один регіон на кожному континенті.

Нам довелося раніше, ніж хотілося, вбудувати в Habitat прозорий для клієнтів шар переміщення даних і маршрутизації, щоб переносити набори даних між обліковими записами з різними топологіями реплікації.

Однак цей підхід теж зрештою впирається в доступні ресурси, тож застосовується лише до кількох ретельно відібраних наборів даних.

Для решти даних покладатися на інтегроване кешування

У навантаженнях Habitat переважає читання: застосунки постійно отримують налаштування, стан та інші властивості. Непропорційно велика частка трафіку припадає на відносно невеликий робочий набір типів даних, до яких часто звертаються. Тому система особливо добре підходить для розподіленого кешування. Кешування підвищує продуктивність інфраструктури в одному регіоні, але в міжрегіональній роботі ефект ще більший: воно дає змогу «приховати» міжрегіональну затримку.

Ми інтегрували в Habitat розподілений шар кешування за схемою lookaside. Він зберігає копії нещодавно запитаних об’єктів і зв’язків на серверах Valkey, розміщених у нашій інфраструктурі поблизу місць обробки користувацьких запитів. Зазвичай такі кеші використовують час життя (TTL), який визначає компроміс між часткою влучань і застарілістю даних. Короткий TTL зменшує застарілість, але послаблює користь кешування: термін зберігання елементів у кеші швидко спливає, тож їх доводиться частіше отримувати знову. Довший TTL підвищує частку влучань, але довше повертає застарілі дані, що погіршує досвід користувачів і робить поведінку продукту непередбачуваною.

Інший підхід — явно інвалідувати кеш, коли застосунок виконує запис у ті самі базові дані. Це значно підвищує актуальність кешованих даних, але правильно реалізувати такий підхід буває складно. До того ж залишаються крайові випадки, як-от часткові збої, через які кеш містить застарілі дані. Багаторегіональні розгортання посилюють ці проблеми через менш надійні міжрегіональні мережі та стан гонитви між кешем і реплікацією базового сховища. Додавання TTL обмежує максимальну застарілість, але не усуває описаного вище компромісу.

Ми обрали досконаліший підхід до інвалідації, наслідуючи такі системи, як TAO від Meta. Інтегрований кеш Habitat використовує відстеження змін даних (CDC) через канал змін Azure Cosmos DB, щоб поширювати інвалідації по всьому світу за лічені секунди. Це забезпечує високу частку влучань за низької застарілості. Сервіс у нашій інфраструктурі читає цей канал змін та інвалідує локальні кеші, коли базові дані оновлюються. Наступне читання цих даних спричиняє промах кешу, після чого кеш заповнюється їхньою найновішою версією.

Зменшити накладні витрати проксі за допомогою Rust

Ми також значно скоротили затримку, усунувши накладні витрати в самому сервісі Habitat: переписали код із Python на продуктивнішу Rust.

Разом ці зміни зменшили загальну глобальну затримку читання p50 приблизно зі 120 мс до 10 мс — у 12 разів відтоді, як на початку цього року ми зосередилися на продуктивності.

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

Milliseconds020406080100120140160Час123
  1. critical data replicated into nearby geos
  2. in-region caching launched
  3. rust rewrite launched

Хоча кешування різко знизило медіанну затримку, найповільніші запити досі потребують отримання некешованих даних із базового сховища, часто у віддалених регіонах. У міру появи нових ресурсів і підвищення ефективності зберігання ми плануємо розв’язати фундаментальніше завдання: від самого початку розміщувати дані ближче до місць, звідки до них звертатимуться.

Масштабування відстеження змін даних

Надійне й масштабоване CDC — передавання змін бази даних до подальших систем — критично важливе не лише для стратегії кешування Habitat. Мільйони змін щосекунди з тисяч контейнерів і мільйонів їхніх розділів проходять через понад сотню топіків Kafka. Вони також забезпечують роботу вторинних індексів з узгодженістю в кінцевому підсумку, конвеєрів переміщення даних, офлайнової аналітики та інших функцій продуктів у реальному часі. З глобальним зростанням базової інфраструктури відстежувати зміни рядків ставало дедалі складніше. Щоб зареєструвати функцію зворотного виклику на кожну зміну рядків свого типу, клієнт має, серед іншого, з’ясувати, які облікові записи й контейнери Cosmos містять його дані, яке розгортання сервісу CDC відстежує ці контейнери у відповідних регіонах, а також належно масштабувати робочі процеси CDC, Kafka та власного споживача. Наша платформа CDC має приховати всі ці деталі від розробників продуктів. Натомість вона надає простий інтерфейс: клієнти реєструють функцію для обробки змінених рядків, а ми беремо на себе всю інфраструктуру й масштабування.

Внутрішня площина керування постійно забезпечує відстеження всіх потрібних контейнерів, вибирає регіони Cosmos для читання й ефективно розподіляє роботу між тисячами робочих процесів у кількох географічних регіонах. Використання регіонів із репліками й читання каналу змін із нижчим пріоритетом захищає чутливий до затримок трафік Habitat від фонового навантаження CDC. У такому великому парку постійно трапляються аварійні завершення робочих процесів, проблеми контейнерів, помилки сховища оренд, некоректні конфігурації та збої цільових систем. Ми підвищили стійкість життєвого циклу робочих процесів CDC й обробки оренд, ізолювали збої між потоками та додали запобіжники для змін конфігурації й розгортань. Ми використовуємо черги недоставлених повідомлень, щоб постійні помилки доставки не блокували початок черги. Ми витримуємо регіональні збої, перемикаючи процеси читання на альтернативні регіони Cosmos. У нашому масштабі довелося навіть змінити CDC SDK від Azure, щоб ефективніше зберігати контрольні точки: накопичувати їх пакетами в пам’яті й лише періодично записувати до сховища.

Хоча внутрішня робота Habitat з Azure Cosmos DB складна, його цінність завжди полягала в приховуванні інфраструктурних деталей від розробників, щоб прискорити створення продуктів. Наша платформа CDC дотримується того самого принципу.

Погляд у майбутнє

Невелика команда змогла підтримувати стрімко зростаючу платформу зберігання, свідомо обмежуючи API сховища, продовжуючи масштабувати сервіс на Python і зосереджуючись на найнагальніших інженерних завданнях. Спочатку ми зосередилися на надійності для критично важливого продуктового трафіку, потім — на продуктивності читання для користувачів у всьому світі, а далі — на ефективній експлуатації у великому масштабі. Цей підхід забезпечив швидке зростання й нові сценарії використання, водночас підвищуючи надійність, продуктивність і швидкість розробки продуктів.

Щоб масштабувати Habitat і сховище розмов для наступного мільярда користувачів, нам потрібно подолати труднощі реплікації даних у нашій інфраструктурі в ще більшому масштабі. Щоб підготуватися до цього заздалегідь, ми розробляємо власну систему онлайн-зберігання ексабайтного масштабу, оптимізовану для об’ємних типів даних Habitat. Ця система, яка ще перебуває в розробці, поєднує ядро RocksDB Cloud від Rockset із реплікацією на основі Raft. Вона реалізує ту саму документну модель, що й Azure Cosmos DB, але використовує відокремлене сховище та фізичну реплікацію, щоб зменшити потрібний обсяг флешпам’яті ціною нижчої пікової кількості запитів за секунду.

Якщо вас цікавить робота над подібною інфраструктурою даних у передових масштабах, перегляньте наші відкриті вакансії⁠.

Автор

OpenAI