Вопрос с собеседования · Highload

Почему удвоение числа серверов не удваивает пропускную способность?

SeniorЗадержка, пропускная способность и очереди
Ещё спрашивают так:
  • Что такое закон Амдала?
  • Что ограничивает горизонтальное масштабирование?
  • Что такое universal scalability law?
Коротко

Масштабируется только параллельная часть работы. Закон Амдала: если 5% работы последовательны, ускорение не превысит 20× при любом числе узлов. А координация между узлами (блокировки, согласование) может даже снижать пропускную способность после некоторого предела.

  • Общие узкие места: одна база, одна блокировка, один лидер, общий счётчик
  • Universal Scalability Law: к последовательной части добавляется цена согласования, растущая как N²
  • Решение — убрать общее: шардирование, локальные кэши, асинхронность, разделение данных

А ещё Перед масштабированием найти, во что упираемся: CPU, база, сеть, блокировка

Подробно

Закон Амдала. Пусть доля p работы распараллеливается, а 1 − p — нет. Ускорение на N узлах: S(N) = 1 / ((1 − p) + p / N). При N → ∞ предел 1 / (1 − p). Даже 95% параллельной работы дают максимум 20×.

В сервисах «последовательная часть» — это всё, что упирается в единственный ресурс:

  • одна основная база или один её мастер для записи;
  • глобальная блокировка или счётчик (SELECT ... FOR UPDATE по одной строке, sequence, распределённая блокировка);
  • единственный лидер в кластере, единственный потребитель партиции;
  • общий кэш или очередь, у которых предел по сети или CPU.

Universal Scalability Law (Нил Гюнтер) добавляет к последовательной части когерентность — цену согласования узлов друг с другом: C(N) = N / (1 + α(N − 1) + βN(N − 1)). Когда β > 0, у кривой есть максимум: после него добавление узлов уменьшает пропускную способность. Так ведут себя системы, где каждый узел общается с каждым: синхронная инвалидация кэшей, распределённые блокировки, широковещательные протоколы.

Как это выглядит на практике — добавили серверов приложений, а RPS не вырос, задержка не упала: значит, узкое место не в них. Пул соединений к базе занят, база упирается в CPU или в блокировки на горячих строках.

Что делать:

  • измерить — найти ресурс с очередью (USE: utilization, saturation, errors для каждого ресурса);
  • уменьшить последовательную часть — шардировать данные, чтобы записи шли в разные узлы; разнести горячие счётчики (шардированные счётчики, агрегирование); заменить синхронное согласование на асинхронное;
  • уменьшить координацию — локальные решения без кворума там, где это допустимо; пакетирование; кэши с TTL вместо синхронной инвалидации;
  • читать с реплик, а писать в шарды — разные узкие места для чтения и записи.

Пример

Обработка заказа: 40 мс параллелится по серверам, 2 мс — UPDATE счётчика
остатка под блокировкой одной строки.
p = 40 / 42 ≈ 0,952 → предел ускорения ≈ 21×.
Больше ~500 заказов/с на один товар не пропустить никаким числом серверов —
пока остаток одного товара обновляется под одной блокировкой.

Что хотят услышать

  • Формула или смысл закона Амдала и предел ускорения.
  • Примеры последовательной части в реальных системах.
  • Цена координации, падение после максимума (USL) — для senior.
  • Как искать узкое место и как уменьшать общую часть.

Частые ошибки

  • Считать, что stateless-сервис масштабируется линейно бесконечно.
  • Масштабировать то, что не является узким местом.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Пропускная способность всегда растёт линейно с числом серверов
  • ✓Ускоряется лишь параллельная часть
  • ✗Последовательная часть работы не влияет на предел ускорения, только на задержку
  • ✗Общая база данных не может быть узким местом при росте серверов

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

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

Разбор собеседования