open atlas
↑ К треку
Основы System Design SD · 09 · 04

Узкие места и трейдоффы

Найди узкое место — ресурс, что ломается первым — и проговори каждый трейдофф: согласованность против доступности, задержка против стоимости, простота против масштаба. Отвечай на «а если 10×?», называя, какой ресурс ломается и почему. Признать трейдофф отличает мидла от сеньора.

SD Middle ◷ 18 min
Уровень
ОсновыJuniorMiddleSenior

«А если трафик вырастет в 10×?» Мидл отвечает «добавим серверов» — правда и почти бессмысленно, потому что не сказано, какая часть падает первой. Сеньор делает паузу, проходит путь запроса и говорит: «stateless-слой нормально масштабируется out, так что не он. При 10× темп записи бьёт ~100K/с, это за пределом комфортной зоны даже шардированной primary, так что узкое место смещается на путь записи — и чтобы держать задержку, мы примем согласованность-в-конечном-счёте на репликах чтения, обменяв свежесть на доступность. Цена — чтения могут быть на пару секунд устаревшими». Тот же вопрос. Один ответ называет ресурс и цену; другой — ни то ни другое. Этот зазор и есть сигнал сеньорности.

Узкое место — один ресурс

Ёмкость системы задаёт её узкое место — единственный ресурс, что насыщается первым при росте нагрузки. Как цепь рвётся в слабейшем звене, вся система встаёт, когда любой единственный ресурс упирается в потолок, сколько бы запаса ни было у других. Добавлять ёмкость где угодно ещё — впустую; нужно найти и расширить связывающее ограничение.

Поэтому, когда дизайн нарисован, пройди путь запроса и спроси на каждом хопе: каков потолок этого компонента и насколько близко к нему нагрузка? Кандидаты-ресурсы всегда из одного короткого списка:

  • CPU на сервис-слое — обычно легче всего починить (масштабировать stateless-слой out).
  • База — пропускная способность primary на запись, или реплики, или единственного горячего шарда. Чаще всего реальное узкое место, потому что состояние сложно масштабировать (урок vertical-vs-horizontal).
  • Горячий ключ или горячий шард — неровная нагрузка, где одна партиция получает непропорциональный трафик, так что средняя утилизация лжёт.
  • Сеть/полоса — egress на fan-out или медиа-тяжёлом пути.
  • Нижестоящая зависимость — сторонний API, общий лок, единственный координатор (член contention из USL — Universal Scalability Law, закон масштабируемости, учитывающий конкуренцию за ресурсы).

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

Почему это работает

Почему узкое место доминирует и почему средняя утилизация про него лжёт? Потому что узкое место задаёт худше всего нагруженный ресурс, не среднее. Кластер базы при 40% средней CPU может плавиться, если один шард держит данные знаменитости и работает на 99% — среднее прячет горячий шард, ровно как средняя задержка прятала хвост в уроке latency-vs-throughput. Поэтому ты ищешь не «занятый слой», а единственный самый горячий ресурс, что часто горячий ключ, горячая партиция или одна синхронная зависимость в иначе параллельном пути. Найди это — и нашёл то, что реально ограничивает систему — а расширять что угодно ещё сначала — движение без прогресса.

Любой дизайн — это набор трейдоффов

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

  • Согласованность против доступности (обмен CAP/PACELC). Строгая согласованность значит координацию, что стоит доступности при разделении и задержки всегда («else, latency» из PACELC). Согласованность-в-конечном-счёте покупает доступность и низкую задержку ценой устаревших чтений. Скажи, что выбрал и почему этот домен это терпит: «счётчик лайков может быть согласован в конечном счёте; баланс банка нет».
  • Задержка против стоимости. Меньше задержка обычно значит больше реплик, больше кэша, больше регионов — всё деньги. Почти любую цель по задержке можно достичь, потратив достаточно; вопрос дизайна — самый дешёвый способ достичь цели, что тебе реально нужна.
  • Простота против масштаба. Простейший дизайн, что вытягивает требования, обычно верен; сложность стоит добавлять лишь там, где оценка форсирует. Один Postgres, что влезает в нагрузку, бьёт шардированную мультирегиональную систему, что тебе не нужна (снова ловушка переинженеринга).
  • Оптимизация чтения против записи. Можно предвычислить на записи, чтобы чтения были дёшевы (fan-out-on-write), или вычислять на чтении, чтобы записи были дёшевы (fan-out-on-read) — но не оба. Отношение чтение/запись паттерна доступа решает, что.

Эти четыре оси покрывают почти каждое архитектурное решение, что тебе придётся принять. Без называния трейдоффа на каждой твой дизайн — набор утверждений; с ним — инженерия. Ход — сказать обмен вслух: «Я выбираю согласованность-в-конечном-счёте тут, что покупает доступность и низкую задержку чтения; цена — чтения могут быть на пару секунд устаревшими, что приемлемо для ленты, но я пересмотрел бы это для платежей». Это одно предложение — разница между ответом и сильным ответом.

Как обрабатывать «а если 10×?»

Вопрос о масштабе — любимый зонд интервьюера, и он проверяет ровно навык узкого места. Неверный ответ — рефлекторное «добавим серверов». Верный ответ — процедура:

  1. Пройди путь и найди новое узкое место. При 10× нагрузке какой ресурс первым пересекает потолок? Пересчитай ключевую оценку (урок оценок): 10× QPS, 10× рост хранилища. Stateless-слой обычно масштабируется out тривиально, так что узкое место почти всегда смещается на stateful-ресурс — primary на запись, горячий шард, кэш, что больше не влезает в RAM.
  2. Назови починку для этого конкретного ресурса и новый трейдофф, что она вносит. «Шардинг слоя записи в 10× значит, что кросс-шард запросы дорожают, поэтому я денормализую частое чтение». Каждая починка смещает узкое место в новое место — скажи, куда оно идёт дальше.
  3. Скажи, что сломается, если ничего не делать, с механизмом: кривая очередей уходит в вертикаль, ретраи наваливаются, и brownout (частичный отказ — система отвечает, но медленно и с ошибками) каскадом в outage (уроки масштабируемости и каскадных отказов).

Что отличает мидла от сеньора

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

Конкретно сеньорские сигналы: определить связывающее узкое место (не «оно медленное», а «primary на запись при 8K/с — это ограничение»); назвать каждый трейдофф с ценой («согласованность-в-конечном-счёте покупает доступность, стоит свежести»); знать режим отказа («за 70% хвост очередей уходит в вертикаль»); и правильно размерить («одного инстанса тут достаточно; шардил бы только за ~10K записей/с»). Уверенность — junior-тель; калиброванная осознанность трейдоффов — сеньорская.

Частая ошибка

Самая частая ошибка трейдоффов — подать дизайн как строго лучший без минусов — «мы используем кэш, что делает быстрее», точка. Интервьюер тут же знает, что ты не продумал, потому что кэш ещё вносит сложность инвалидации, окно согласованности, thundering herd на холодном старте и новый режим отказа (что будет, когда кэш ляжет?). Каждый добавленный компонент что-то покупает и что-то стоит. Лечение — рефлекс: после каждого выбора дизайна спроси себя «и что это мне стоило?» и скажи ответ вслух. Инженер, что сам называет минус своего решения, куда достовернее того, кого приходится загонять в угол, чтобы признал.

Викторина

Интервьюер спрашивает «а если трафик вырастет в 10×?». Какой ответ показывает сеньорское рассуждение об узком месте?

Викторина

Кластер базы показывает 40% средней CPU, но пользователи жалуются на таймауты. Каково наиболее вероятное узкое место и почему среднее вводит в заблуждение?

Закончи аналогию

Сеньорский ответ от мидлового отличает явное называние _______: констатация, что выбор (скажем, согласованность-в-конечном-счёте) покупает одно свойство (доступность, низкую задержку) ценой другого (устаревшие чтения), а не подача дизайна как строго лучшего без минусов.

Вспомните перед уходом
  1. 01
    Как найти узкое место и почему средняя утилизация вводит в заблуждение?
  2. 02
    Назови повторяющиеся оси трейдоффов и как хорошо проговорить одну.
  3. 03
    Какова процедура для вопроса «10× трафика» и в чём разница сеньора и мидла?
Итог

Ёмкость системы задаёт её узкое место — единственный ресурс, что насыщается первым — поэтому ты проходишь путь запроса и находишь, к потолку какого компонента нагрузка ближе всего, используя раннюю оценку. Кандидаты всегда: CPU (легко, масштабировать stateless-слой out), база (обычно реальное), горячий ключ или горячий шард (где средняя утилизация лжёт — кластер 40% может плавиться на одном шарде у 99%), сеть или нижестоящая зависимость. Затем подавай каждый выбор как осознанный трейдофф с названной ценой: согласованность против доступности (обмен CAP/PACELC — «счётчик лайков может устареть, баланс банка нет»), задержка против стоимости, простота против масштаба, оптимизация чтения против записи. Обрабатывай «а если 10×?» как процедуру — пересчитай оценку, найди ресурс, что теперь ломается первым (почти всегда stateful), назови точечную починку и её новый трейдофф и скажи, куда узкое место смещается дальше и что каскадирует, если ничего не делать. Сквозная линия и весь смысл этого юнита — сигнал сеньорности: уверенность — junior-тель; назвать связывающее узкое место, цену каждого трейдоффа, режим отказа и правильный размер — сеньорский. Сам назови минус своего решения, прежде чем тебя загонят в него. Теперь, когда слышишь «а если 10×?» или «зачем ты это добавил?», первый ход — пройти путь запроса, найти единственный ресурс, что ломается первым, и назвать его цену — а не тянуться за названием паттерна.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 7 завершено
Связанные уроки

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

Примени это

Примени этот урок в реальном проекте.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.