Методология системного дизайна
Как вести системный дизайн на интервью — сбор функциональных и нефункциональных требований, оценка нагрузки, бюджеты доступности, выбор стиля API, HLD против LLD и типичные ошибки.
8 вопросов
JuniorТеорияОчень частоЧем функциональные требования отличаются от нефункциональных?
Чем функциональные требования отличаются от нефункциональных?
Функциональные требования говорят, что система делает: роли пользователей, права каждой роли, поиск по ключевым словам с фильтрами, способы оплаты. Нефункциональные говорят, насколько хорошо: DAU/MAU, рост, соотношение чтения и записи, retention, цели по латентности.
Типичные ошибки
- ✗Перечислять только функции и забывать нефункциональные числа: DAU, рост, соотношение чтения и записи
- ✗Считать цели по латентности и доступности функциональными требованиями, а не нефункциональными
- ✗Кидаться в архитектуру до того, как с интервьюером записано хоть одно требование
Уточняющие вопросы
- →Какое нефункциональное число сильнее всего влияет на архитектуру и почему?
- →Как соотношение чтения и записи изменит выбор хранилища и кеширования?
MiddleДизайнОчень частоУ маркетплейса 30M активных пользователей в день (DAU), по 8 действий в день на пользователя, загрузка объекта 500KB, соотношение чтение/запись 80/20, retention 3 года и дневной пик 5x — оцени средний и пиковый QPS (запросов в секунду), хранилище и полосу в год и назови компоненты, которые эти числа нагружают.
У маркетплейса 30M активных пользователей в день (DAU), по 8 действий в день на пользователя, загрузка объекта 500KB, соотношение чтение/запись 80/20, retention 3 года и дневной пик 5x — оцени средний и пиковый QPS (запросов в секунду), хранилище и полосу в год и назови компоненты, которые эти числа нагружают.
Средний QPS записи = 30M8/86400 ≈ 2.8k; пик = 2.8k5 ≈ 14k QPS записи, а при 80/20 пик чтений ≈56k. Хранилище/год = объекты/день500KB3 года; полоса растёт с пиком чтений. Эти числа нагружают путь записи, хранилище и кэш — это обосновывает шардирование и CDN.
Типичные ошибки
- ✗Пропустить оценку и сразу прыгнуть к архитектуре, из-за чего выбор компонентов ничем численно не обоснован.
- ✗Считать пик делением среднего на пиковый коэффициент вместо умножения, занижая размер системы.
- ✗Забыть про соотношение чтение/запись, из-за чего ёмкость и полоса под тяжёлый путь чтения не оцениваются.
Уточняющие вопросы
- →В какое время суток приходится пик 5x и чем он вызван?
- →Какое из чисел сильнее всего меняет выбор уровня хранилища?
MiddleДизайнОчень частоСпроектируйте высокоуровневую архитектуру сервиса заказов маркетплейса (продавцы, покупатели, оплата), затем объясните, чем этот HLD отличается от низкоуровневого дизайна, который вы напишете после.
Спроектируйте высокоуровневую архитектуру сервиса заказов маркетплейса (продавцы, покупатели, оплата), затем объясните, чем этот HLD отличается от низкоуровневого дизайна, который вы напишете после.
HLD — это блоки и стрелки: сервисы, хранилища и очереди с подписанными потоками данных. Рисуйте от пользователя, считайте один датацентр и избегайте циклических зависимостей. LLD идёт после — схемы, индексы, сигнатуры API и дизайн struct/interface.
Типичные ошибки
- ✗Сразу прыгаете в схемы таблиц и выбор индексов, не нарисовав сначала сервисы, хранилища и подписанные потоки данных.
- ✗Рисуете стрелки между сервисами без подписей, и непонятно, какие данные или запрос реально пересекают каждое ребро.
- ✗Допускаете циклические зависимости между сервисами в HLD, из-за чего нельзя рассуждать о владении и порядке деплоя.
Уточняющие вопросы
- →Где на этом HLD оплата и какая стрелка несёт событие заказа?
- →Как вы разобьёте этот один блок на конкретные таблицы и индексы в LLD?
JuniorТеорияЧастоКогда выбирать REST вместо gRPC для сервиса и почему?
Когда выбирать REST вместо gRPC для сервиса и почему?
Бери REST для внешних публичных API, удобных для отладки и кеширования и легко вызываемых из браузера. Бери gRPC для внутренних вызовов сервис-сервис: бинарный protobuf, стриминг по HTTP/2, типизированные контракты, ниже латентность. Обоснуй по внутренний-против-внешнего.
Типичные ошибки
- ✗Утверждение, что gRPC повсеместно быстрее, и выбор его по умолчанию даже для публичных, браузерных эндпоинтов.
- ✗Отношение к REST и gRPC как к взаимозаменяемым и отсутствие обоснования выбора по внутренний-против-внешнего.
- ✗Забывают, что реальное преимущество gRPC — стриминг и типизированные protobuf-контракты, а не только скорость.
Уточняющие вопросы
- →Как стриминг gRPC меняет дизайн по сравнению с запрос-ответ REST?
- →Почему REST проще кешировать и отлаживать на сетевом краю?
MiddleТеорияЧастоЧем отличаются SLA, SLO и SLI и как они связаны с нефункциональными требованиями?
Чем отличаются SLA, SLO и SLI и как они связаны с нефункциональными требованиями?
SLA — это внешнее контрактное обещание клиентам с денежными штрафами за нарушение. SLO — более строгая внутренняя цель: ставишь её жёстче, чтобы алертить до угрозы SLA. SLI — измеряемый индикатор, на котором определён SLO, например латентность p99 или доля успешных запросов. Они превращают размытые нефункциональные требования в числа, и ты не обещаешь девяток, которые не потянешь.
Типичные ошибки
- ✗Путать определения — называть SLA внутренней целью, а SLO контрактом с клиентом
- ✗Обещать девятки в SLA без измеряемого SLI и без запаса SLO, чтобы алертить до нарушения
- ✗Считать SLA/SLO/SLI оторванными от нефункциональных требований, которые их и задают
Уточняющие вопросы
- →Зачем делать SLO строже SLA, а не ставить их равными?
- →Какие SLI ты выберешь для нагруженного на запись API маркетплейса?
JuniorТеорияИногдаЧто означают 99.9% и 99.99% доступности в часах простоя за год и почему каждая лишняя девятка дороже?
Что означают 99.9% и 99.99% доступности в часах простоя за год и почему каждая лишняя девятка дороже?
Доступность — это доля года, когда сервис работает, поэтому остаток и есть твой бюджет простоя. 99.9% (три девятки) дают примерно 8.76ч/год, а 99.99% (четыре девятки) урезают это до примерно 52.6мин/год. Каждая добавленная девятка режет бюджет в ~10 раз, поэтому примерно во столько же раз растут стоимость и сложность — резервирование, failover и тестирование.
Типичные ошибки
- ✗Говорить, что 99.9% — это
52.6мин/год (это 99.99%) — путать три девятки с четырьмя - ✗Обещать пять девяток без резервирования и бюджета на дежурства, чтобы их реально держать
- ✗Считать каждую лишнюю девятку малой линейной добавкой, а не скачком сложности примерно в 10 раз
Уточняющие вопросы
- →Чем отличаются SLA, SLO и SLI и за какой из них платят штрафы?
- →Какие изменения архитектуры дают переход с трёх девяток на четыре?
SeniorДизайнИногдаТы только что закончил проектировать на Go сервис-маркетплейс с одним инстансом Postgres, и интервьюер спрашивает, как ты сделаешь его операционно готовым до того, как он примет реальный продакшен-трафик. Сам дизайн считай зафиксированным — вопрос только про эксплуатацию. Ограничения: мультисервисное развёртывание, где один запрос пользователя расходится по нескольким Go-сервисам; потеря данных недопустима, а схема будет меняться от релиза к релизу; команда должна быстро обнаруживать и диагностировать инциденты. Опиши, какие эксплуатационные практики ты внедришь, в каком порядке их примешь и как решишь, когда выходить за пределы одного Postgres.
Ты только что закончил проектировать на Go сервис-маркетплейс с одним инстансом Postgres, и интервьюер спрашивает, как ты сделаешь его операционно готовым до того, как он примет реальный продакшен-трафик. Сам дизайн считай зафиксированным — вопрос только про эксплуатацию. Ограничения: мультисервисное развёртывание, где один запрос пользователя расходится по нескольким Go-сервисам; потеря данных недопустима, а схема будет меняться от релиза к релизу; команда должна быстро обнаруживать и диагностировать инциденты. Опиши, какие эксплуатационные практики ты внедришь, в каком порядке их примешь и как решишь, когда выходить за пределы одного Postgres.
Настрой бэкапы — полные, инкрементальные и point-in-time — и докажи их протестированным восстановлением, ведь непротестированный бэкап бэкапом не считается. Применяй forward-only версионированные миграции схемы, добавь метрики и мониторинг и распределённый трейсинг, чтобы проследить один запрос по сервисам. Начни с одного Postgres и масштабируйся только когда требование вынудит.
Типичные ошибки
- ✗Перечисляешь бэкапы, но не проверяешь их учением по восстановлению — непротестированный бэкап молча подведёт в нужный день.
- ✗Считаешь точечные или обратимые правки схемы нормой — неверсионированные изменения разводят окружения и ломают повторное применение.
- ✗Пропускаешь распределённый трейсинг — запрос, расходящийся по Go-сервисам, становится невозможно проследить сквозь систему.
Уточняющие вопросы
- →Какой целевой срок восстановления решает между point-in-time и ночным полным бэкапом?
- →Когда конкретное требование оправдывает выход за пределы одного Postgres?
SeniorТеорияРедкоНазови классические ошибки на системном дизайне и какая дисциплина удерживает решение от них?
Назови классические ошибки на системном дизайне и какая дисциплина удерживает решение от них?
Тянешь технологию, которую не понимаешь, проектируешь сверх требований, вываливаешь все знания напоказ, игнорируешь продуктовые метрики и переусложняешь. Дисциплина — начинай с простого и добавляй сложность только когда конкретное требование вынуждает это.
Типичные ошибки
- ✗Перечисляешь ошибки, но не называешь лекарство — начинай с простого и масштабируй только когда требование вынуждает.
- ✗Считаешь переусложнение осторожностью — лишние кэши и очереди добавляют точки отказа без пользы.
- ✗Путаешь широту с глубиной — пересказ всех фактов игнорирует реальные требования и метрики.
Уточняющие вопросы
- →Когда конкретное требование оправдывает добавление кэша или очереди?
- →Как продуктовые метрики меняют, какой компонент оптимизируешь первым?