System Design Interview
Введение
System Design интервью - это один из ключевых этапов собеседования на позиции senior+ инженеров. В отличие от алгоритмических задач, здесь нет “правильного” ответа. Интервьюер оценивает ваше умение анализировать требования, проектировать масштабируемые системы, обсуждать trade-off’ы и коммуницировать свои решения.
Эта методичка построена на основе опыта прохождения интервью и классических ресурсов: Designing Data-Intensive Applications Мартина Клеппманна и System Design Interview Алекса Сю. Основная техническая база по системному дизайну находится в заметке System Design - здесь мы фокусируемся именно на процессе прохождения интервью.
Summary
Что вы найдёте в этой заметке:
- Фреймворк прохождения интервью из 5 фаз
- Два полных разбора: WhatsApp (write-heavy, real-time) и URL Shortener (read-heavy, simple)
- Инфраструктурный реализм: как выглядит система в реальном датацентре
- Чек-лист подготовки и типичные ошибки
Фреймворк прохождения интервью
Что оценивает интервьюер
System Design интервью - это не экзамен на знание конкретных технологий. Интервьюер оценивает четыре компетенции:
| Компетенция | Что проверяется | Как проявить |
|---|---|---|
| Анализ проблемы | Умеете ли вы задавать правильные вопросы, а не сразу предлагать решение | Начинайте с уточнения требований |
| Знание системного дизайна | Понимаете ли вы масштабирование, отказоустойчивость, trade-off’ы | Объясняйте почему вы выбрали именно это решение |
| Коммуникация | Умеете ли вы структурировать мысли и вести диалог | Говорите вслух, рисуйте диаграммы, задавайте вопросы |
| Анализ trade-off’ов | Видите ли вы плюсы и минусы каждого решения | Всегда предлагайте 2-3 альтернативы и объясняйте выбор |
Important
Интервьюер оценивает процесс мышления, а не конечное решение. Нет “правильного” ответа - есть обоснованный подход с учётом ограничений.
Пятифазный фреймворк
Каждое System Design интервью длится 45-60 минут. Оптимальное распределение времени:
| Фаза | Время | Цель |
|---|---|---|
| 1. Требования | 2-3 мин | Уточнить функциональные и нефункциональные требования |
| 2. Оценка масштаба | 5-10 мин | Посчитать QPS, хранилище, пропускную способность |
| 3. Высокоуровневый дизайн | 10-15 мин | Нарисовать архитектуру из 3-5 компонентов |
| 4. Углубление | 15-25 мин | Разобрать 2-3 компонента детально, обсудить trade-off’ы |
| 5. Завершение | 3-5 мин | Обсудить мониторинг, сценарии отказа, масштабирование |
Summary
60 минут = 3 мин требования + 10 мин оценка + 15 мин HLD + 25 мин deep dive + 5 мин wrap-up + 2 мин буфер
Фаза 1: Сбор требований
Что делать:
- Задавать уточняющие вопросы до того, как начнёте проектировать
- Определить функциональные требования (что система делает)
- Определить нефункциональные требования (как система работает)
Что спросить у интервьюера:
- “Какой масштаб мы рассматриваем - миллионы или миллиарды пользователей?”
- “Какие функции обязательны, а какие опциональны?”
- “Есть ли ограничения по latency или доступности?”
- “Нужна ли поддержка мобильных приложений и веба одновременно?”
Типичные ошибки:
- Начинать проектировать без уточнения требований
- Предполагать требования вместо того, чтобы спросить
- Упускать нефункциональные требования (доступность, консистентность)
Пример диалога:
Кандидат: “Прежде чем начать, хочу уточнить несколько моментов. Для скольких пользователей мы проектируем систему?”
Интервьюер: “Допустим, 100 миллионов DAU.”
Кандидат: “Отлично. А какие функции обязательны - только отправка сообщений или также групповые чаты и медиа?”
Фаза 2: Оценка масштаба
Что делать:
- Сделать back-of-the-envelope расчёты
- Посчитать QPS (queries per second)
- Оценить объём хранилища
- Оценить пропускную способность сети
Как считать:
- DAU × действий в день ÷ 86400 = write QPS
- Read QPS обычно в 5-10 раз выше write QPS
- Объём = количество записей × средний размер записи
- Пропускная способность = QPS × размер запроса
Пример расчёта для мессенджера:
DAU: 200 миллионов
Сообщений на пользователя в день: 10
Всего сообщений в день: 2 миллиарда
Write QPS: 2B ÷ 86400 ≈ 23 000
Read QPS: 23 000 × 10 ≈ 230 000 (каждое сообщение читают ~10 человек)
Средний размер сообщения: 100 байт
Хранилище в день: 2B × 100B = 200 ГБ
Хранилище в год: 200 ГБ × 365 ≈ 73 ТБ
Типичные ошибки:
- Не показывать расчёты на доске / в редакторе
- Забывать про пиковую нагрузку (peak может быть в 2-3 раза выше среднего)
- Не учитывать рост (система будет работать не один день)
Фаза 3: Высокоуровневый дизайн
Что делать:
- Нарисовать архитектуру из 3-5 компонентов
- Определить API endpoints
- Определить модель данных
- Показать поток данных между компонентами
Принципы:
- Начинайте просто - 3-5 прямоугольников с подписями
- Используйте стандартные компоненты: Load Balancer, API Gateway, Application Server, Database, Cache, Message Queue
- Не углубляйтесь в детали - это только высокоуровневый взгляд
Пример архитектуры (мессенджер):
┌─────────┐ ┌─────────────┐ ┌─────────────────┐ ┌──────────┐
│ Client │────→│ API Gateway │────→│ App Servers │────→│ Database │
└─────────┘ └─────────────┘ └─────────────────┘ └──────────┘
│
↓
┌─────────────┐
│ Message │
│ Queue │
└─────────────┘
Типичные ошибки:
- Переусложнять архитектуру с первого шага
- Не объяснять поток данных
- Пропускать API или модель данных
Фаза 4: Углубление
Что делать:
- Выбрать 2-3 компонента для детального разбора
- Обсудить trade-off’ы для каждого решения
- Объяснить выбор конкретной технологии
Как выбрать компоненты:
- Спросите интервьюера: “В какую часть системы стоит углубиться?”
- Если интервьюер не направляет, выберите наиболее интересные компоненты:
- Для мессенджера: доставка сообщений, хранение, масштабирование БД
- для URL shortener: генерация коротких ссылок, кэширование, выбор БД
Структура обсуждения trade-off’ов:
- “У нас есть несколько подходов…”
- “Подход A даёт X, но требует Y…”
- “Подход B даёт Z, но сложнее в настройке…”
- “Я выбираю подход A, потому что…”
Пример trade-off (выбор БД):
“Для хранения сообщений можно использовать SQL или NoSQL. SQL даёт ACID и сложные запросы, но сложнее масштабировать горизонтально. NoSQL легко шардировать, но eventual consistency может означать, что сообщения временно не видны всем участникам чата. Для мессенджера я бы выбрал NoSQL с настройкой strong consistency для критичных операций.”
Типичные ошибки:
- Не обсуждать альтернативы
- Защищать своё решение эмоционально вместо того, чтобы аргументировать
- Углубляться в нерелевантные детали (например, специфику конкретной версии PostgreSQL)
Фаза 5: Завершение
Что делать:
- Обсудить мониторинг и метрики
- Рассмотреть сценарии отказа
- Упомянуть будущее масштабирование
Мониторинг:
- Какие метрики отслеживать (latency, error rate, throughput)
- Какие алерты настроить
- Какие дашборды использовать
Сценарии отказа:
- “Что если упадёт одна нода БД?”
- “Что если откажет центр обработки данных?”
- “Как обеспечить zero-downtime deployment?”
Будущее масштабирование:
- “Если пользователей станет в 10 раз больше…”
- “Если добавим новую функцию (например, видеозвонки)…”
Типичные ошибки:
- Забывать про мониторинг
- Не обсуждать failure scenarios
- Заканчивать слишком быстро без wrap-up
Коммуникационные паттерны
Что говорить на каждой фазе
Начало интервью:
“Спасибо за задачу. Прежде чем начать проектировать, хочу уточнить несколько требований. Так я смогу предложить более точное решение.”
При переходе между фазами:
“Требования уточнены. Давайте оценим масштаб системы…” “Расчёты готовы. Теперь нарисую высокоуровневую архитектуру…” “Архитектура готова. В какую часть системы стоит углубиться?”
При обсуждении trade-off’ов:
“Здесь есть несколько подходов. Давайте рассмотрим плюсы и минусы каждого…” “Я склоняюсь к варианту X, потому что… Но при условии Y вариант Z тоже имеет смысл.”
При получении pushback от интервьюера:
“Хороший вопрос. Давайте подумаем, как это повлияет на архитектуру…” “Вы правы, этот подход имеет ограничение. Альтернатива - …”
Как обрабатывать неизвестные вопросы
Если интервьюер спрашивает о технологии, которую вы не знаете:
“Честно говоря, я не работал с X напрямую. Но я знаю, что в этой области есть подходы Y и Z. Если X решает похожую задачу, я бы изучил его trade-off’ы перед выбором.”
Это показывает:
- Честность (не выдумываете знания)
- Гибкость мышления (готовы изучить новое)
- Понимание домена (знаете альтернативы)
Типичные ошибки и как их избежать
Ошибка 1: Начать решать без уточнения требований
Почему это проблема: Вы можете спроектировать систему для неправильного масштаба или упустить критичные требования.
Как избежать: Всегда начинайте с вопросов. Даже если требования кажутся очевидными, уточните масштаб и приоритеты.
Ошибка 2: Игнорировать нефункциональные требования
Почему это проблема: Доступность 99.9% и 99.999% - это разные архитектуры. eventual consistency и strong consistency - разные решения.
Как избежать: Явно спросите про availability, consistency, latency требования.
Ошибка 3: Переусложнять с первого шага
Почему это проблема: Сложная архитектура из 15 компонентов трудно объяснить и отлаживать. Интервьюер оценивает процесс, а не количество компонентов.
Как избежать: Начинайте с 3-5 компонентов. Усложняйте только там, где это обосновано.
Ошибка 4: Не обсуждать trade-off’ы
Почему это проблема: Каждое решение имеет цену. Если вы не обсуждаете альтернативы, интервьюер не видит глубины вашего понимания.
Как избежать: Для каждого ключевого решения предлагайте 2-3 альтернативы и объясняйте выбор.
Ошибка 5: Молчать или думать про себя
Почему это проблема: Интервьюер не видит ваш процесс мышления. Вы можете прийти к правильному ответу, но не получить credit за путь.
Как избежать: Думайте вслух. Объясняйте каждый шаг. Рисуйте на доске или в редакторе.
Ошибка 6: Не оценивать масштаб
Почему это проблема: Без расчётов вы не можете обосновать выбор технологий. SQL может быть нормально для 1000 пользователей, но не для 100 миллионов.
Как избежать: Всегда делайте back-of-the-envelope расчёты. Показывайте их на доске.
Ошибка 7: Забывать про мониторинг и отказы
Почему это проблема: Production система без мониторинга - это чёрный ящик. Без плана отказов - это система, которая упадёт при первой проблеме.
Как избежать: Завершайте интервью обсуждением monitoring, alerting, failure scenarios.
Ошибка 8: Защищать ошибочное решение
Почему это проблема: Интервьюер может указывать на реальные проблемы. Защита “до последнего” показывает негибкость.
Как избежать: Будьте открыты к feedback. “Вы правы, это создаёт bottleneck. Давайте пересмотрим этот компонент.”
Ошибка 9: Не спрашивать направления у интервьюера
Почему это проблема: Интервьюер может быть заинтересован в конкретной области. Если вы углубляетесь не туда, теряете время.
Как избежать: Спрашивайте: “В какую часть системы стоит углубиться?” или “Что для вас наиболее интересно в этом дизайне?”
Разбор: WhatsApp Messenger
В этом разборе мы проходим все пять фаз интервью на примере проектирования мессенджера, похожего на WhatsApp. Требования взяты из реального домашнего задания и адаптированы для формата интервью.
Фаза 1: Требования
Диалог с интервьюером:
Кандидат: “Прежде чем начать, хочу уточнить масштаб и функции. Для скольких пользователей мы проектируем?”
Интервьюер: “200 миллионов DAU.”
Кандидат: “Какие функции обязательны? Отправка текстовых сообщений, групповые чаты, медиа?”
Интервьюер: “Текстовые сообщения, групповые чаты до 256 участников, изображения и видео, статус доставки и прочтения, синхронизация между устройствами.”
Кандидат: “Есть ли требования к latency и доступности?”
Интервьюер: “Доставка сообщений менее 200 мс, доступность 99.99%.”
Функциональные требования:
- Отправка и получение текстовых сообщений в личных и групповых чатах
- Групповые чаты до 256 участников
- Статус сообщений: отправлено, доставлено, прочитано
- Онлайн / оффлайн статус пользователей
- Отправка медиа: изображения, видео, документы
- Синхронизация между несколькими устройствами
Нефункциональные требования:
- Доступность: 99.99%
- Latency: менее 200 мс на доставку сообщения
- Консистентность: сообщения должны приходить в порядке отправки
- Масштаб: 200 миллионов DAU
Фаза 2: Оценка масштаба
Диалог:
Кандидат: “Давайте оценим масштаб. Сколько сообщений отправляет один пользователь в день?”
Интервьюер: “В среднем 10 сообщений в день.”
Кандидат: “Отлично. Тогда общий объём:”
Расчёты:
DAU: 200 000 000
Сообщений на пользователя в день: 10
Всего сообщений в день: 2 000 000 000
Write QPS: 2 000 000 000 ÷ 86 400 ≈ 23 000
Read QPS: 23 000 × 10 ≈ 230 000
(каждое сообщение читают примерно 10 человек в среднем)
Средний размер текстового сообщения: 100 байт
Хранилище текстов в день: 2B × 100B = 200 ГБ
Хранилище текстов в год: 200 ГБ × 365 ≈ 73 ТБ
Медиа:
- Изображения: 10% сообщений, средний размер 1 МБ
- Видео: 2% сообщений, средний размер 10 МБ
- Хранилище медиа в день: ~40 ТБ
Important
Пиковая нагрузка может быть в 2-3 раза выше средней. Для peak write QPS считаем ~70 000.
Фаза 3: Высокоуровневый дизайн
Архитектура:
┌─────────┐ ┌─────────────┐ ┌─────────────────┐ ┌──────────┐
│ Client │────→│ API Gateway │────→│ App Servers │────→│ Database │
│ (Mobile │ │ (Rate Limit,│ │ (WebSocket │ │ (Messages,│
│ Web, │ │ Auth) │ │ handlers, │ │ Users, │
│ Desktop)│ │ │ │ business logic)│ │ Chats) │
└─────────┘ └─────────────┘ └─────────────────┘ └──────────┘
│
↓
┌─────────────┐
│ Message │
│ Queue │
│ (Kafka / │
│ RabbitMQ) │
└─────────────┘
│
↓
┌─────────────┐
│ Push │
│ Notification│
│ Service │
└─────────────┘
│
↓
┌─────────────┐
│ Object │
│ Storage │
│ (S3) │
└─────────────┘
API Design:
| Method | Endpoint | Описание |
|---|---|---|
| POST | /messages | Отправить сообщение |
| GET | /messages?chat_id={id}&limit=50 | Получить сообщения чата |
| GET | /users/{id}/status | Получить статус пользователя |
| POST | /media/upload | Загрузить медиафайл |
| GET | /media/{id} | Получить медиафайл |
| POST | /chats | Создать чат |
| GET | /chats/{id}/members | Получить участников чата |
Модель данных:
users
- id (PK)
- username
- phone_number
- last_seen
- public_key (для E2E encryption)
- created_at
chats
- id (PK)
- type (1:1 / group)
- name (для групп)
- created_at
chat_members
- chat_id (FK)
- user_id (FK)
- joined_at
- role (admin / member)
messages
- id (PK)
- chat_id (FK)
- sender_id (FK)
- content (текст или ссылка на медиа)
- type (text / image / video / file)
- sequence_number (для порядка в чате)
- status (sent / delivered / read)
- created_at
media
- id (PK)
- message_id (FK)
- url (ссылка на S3)
- type (image / video / file)
- size
- created_at
Фаза 4: Углубление
Тема 1: Доставка сообщений в реальном времени
Диалог:
Кандидат: “Ключевой вопрос - как обеспечить доставку сообщений менее чем за 200 мс. Для активных пользователей я бы использовал WebSocket соединения.”
Интервьюер: “А что делать с пользователями, которые оффлайн?”
Кандидат: “Хороший вопрос. Для оффлайн-пользователей сообщения сохраняются в базе данных. Когда пользователь подключается, мы отправляем все пропущенные сообщения.”
Подход:
- Активные пользователи: WebSocket соединение для real-time доставки
- Оффлайн пользователи: сообщения сохраняются в БД, доставляются при подключении
- Статусы: sent → delivered → read
Trade-off:
- WebSocket даёт низкую latency, но требует держать много открытых соединений
- Long polling проще, но latency выше
- Выбор: WebSocket для real-time, fallback на long polling
Тема 2: Масштабирование базы данных
Диалог:
Кандидат: “С 23 000 write QPS и 230 000 read QPS одна нода БД не справится. Нужно шардирование.”
Интервьюер: “По какому ключу будем шардировать?”
Кандидат: “Есть два подхода. По chat_id - история чата остаётся на одном шарде, что упрощает чтение. По user_id - нагрузка распределяется равномернее. Я бы выбрал шардирование по chat_id с репликацией для чтения.”
Подход:
- Шардирование по chat_id (консистентность истории чата)
- Read replicas для снижения нагрузки на чтение
- Кэширование последних сообщений в Redis
Trade-off:
- Шардирование по chat_id: проще чтение, но hot chats создают hotspot
- Шардирование по user_id: равномерная нагрузка, но чтение истории требует запросов к нескольким шардам
- Выбор: Шардирование по chat_id + мониторинг hotspot’ов
Тема 3: Хранение медиа
Диалог:
Кандидат: “Медиафайлы занимают значительно больше места, чем текст. 40 ТБ в день - это требует отдельного подхода.”
Интервьюер: “Как бы вы хранили медиа?”
Кандидат: “Object storage, например S3. Файлы загружаются напрямую в S3 через presigned URL. В сообщении хранится только ссылка. Для быстрой доставки используем CDN.”
Подход:
- Object Storage (S3) для долговременного хранения
- Presigned URLs для загрузки напрямую из клиента
- CDN для глобальной доставки
- Сжатие изображений и транскодирование видео
Trade-off:
- Object storage дешевле, но latency выше, чем у локального хранилища
- CDN ускоряет доставку, но добавляет стоимость
- Выбор: S3 + CDN для production, локальное хранилище для недавних файлов
Тема 4: Синхронизация между устройствами
Диалог:
Кандидат: “Пользователь может быть одновременно на телефоне и на компьютере. Нужна синхронизация.”
Интервьюер: “Как бы вы это реализовали?”
Кандидат: “Каждое устройство поддерживает WebSocket соединение. Для синхронизации используем sequence_number сообщений. Каждое устройство знает последнее прочитанное sequence_number и запрашивает только новые сообщения.”
Подход:
- Отдельное WebSocket соединение на устройство
- Sequence numbers для порядка сообщений
- sync_protocol: last_seen_sequence_number на устройстве
- Conflict resolution: server wins (last write)
Trade-off:
- Много соединений на пользователя = больше ресурсов сервера
- Но необходимо для кросс-девайс опыта
- Выбор: Поддержка до 3-5 устройств на пользователя с балансировкой нагрузки
Фаза 5: Завершение
Мониторинг:
| Метрика | Почему важна |
|---|---|
| Message delivery latency (p50, p95, p99) | Проверяем SLA в 200 мс |
| Failed message rate | Должно быть менее 0.01% |
| Active WebSocket connections | Планирование capacity |
| Storage growth rate | Планирование расширения |
| Error rate by component | Быстрое обнаружение проблем |
Сценарии отказа:
| Отказ | Решение |
|---|---|
| Нода БД недоступна | Промоутить read replica в master |
| Сервер WebSocket упал | Клиент переподключается к другому серверу |
| Message Queue недоступна | Локальная буферизация с retry |
| Датацентр недоступен | Multi-region replication, failover |
Будущее масштабирование:
- Федерация: поддержка сообщений между разными сервисами (interoperability)
- End-to-end encryption: Signal Protocol для приватности
- Исчезающие сообщения: автоудаление через заданное время
- Голосовые сообщения и видеозвонки: WebRTC интеграция
Инфраструктурный реализм
В System Design интервью важно показать, что вы понимаете не только абстрактную архитектуру, но и реальные физические ограничения. Этот раздел покрывает инфраструктурные детали, которые часто спрашивают на интервью или которые отличают хорошего кандидата.
Физическая инфраструктура
Стойки и серверы
Стандартная серверная стойка имеет высоту 42U (units). Каждый unit - это 1.75 дюйма (44.45 мм).
| Параметр | Типичное значение |
|---|---|
| Высота стойки | 42U (~1.8 метра) |
| Серверов в стойке | 20-40 (в зависимости от высоты сервера: 1U или 2U) |
| Мощность стойки | 5-10 кВт |
| Сетевой коммутатор | 10-100 Gbps (top-of-rack) |
Info
1U сервер занимает 1 unit, 2U - два unit’а. Более мощные серверы обычно 2U из-за большего количества дисков и лучшего охлаждения.
Диски и хранилище
| Тип | Ёмкость | IOPS | Задержка | Применение |
|---|---|---|---|---|
| NVMe SSD | 1-8 ТБ | ~500 000 | ~50 мкс | Базы данных, hot data |
| SATA SSD | 1-8 ТБ | ~100 000 | ~100 мкс | Базы данных, кэши |
| HDD | 8-20 ТБ | ~200 | ~5 мс | Холодное хранение, бэкапы |
Ключевое наблюдение для интервью:
Important
Разница в latency между RAM и SSD - в 1000 раз. Между SSD и HDD - ещё в 50 раз. Это определяет архитектурные решения: hot data в RAM/SSD, cold data на HDD.
Конфигурация дисков в стойке:
- Типичный сервер базы данных: 8-16 NVMe SSD по 4 ТБ = 32-64 ТБ
- Типичный сервер хранения: 12-24 HDD по 16 ТБ = 192-384 ТБ
- Одна стойка с 20 серверами БД: ~640 ТБ - 1.3 ПБ SSD
- Одна стойка с 20 серверами хранения: ~3.8 - 7.7 ПБ HDD
Сеть и latency
| Расстояние | Задержка | Пример |
|---|---|---|
| Внутри датацентра | < 1 мс | Два сервера в одном здании |
| Внутри региона | 5-20 мс | Восточное побережье США |
| Между регионами | 20-50 мс | Восточное и западное побережье |
| Между континентами | 50-200 мс | США - Европа |
| Вокруг земного шара | 150-300 мс | США - Азия |
Пропускная способность:
| Подключение | Пропускная способность |
|---|---|
| 1 Gbps | ~125 МБ/с |
| 10 Gbps | ~1.25 ГБ/с |
| 40 Gbps | ~5 ГБ/с |
| 100 Gbps | ~12.5 ГБ/с |
Info
В интервью полезно знать: 10 Gbps - стандарт для современных датацентров. Один сервер с 10 Gbps может передать 1 ТБ за ~15 минут.
Память
| Тип | Ёмкость на сервер | Задержка |
|---|---|---|
| DDR4 RAM | 64-512 ГБ | ~100 нс |
| DDR5 RAM | 128-1024 ГБ | ~80 нс |
Important
RAM в 1000 раз быстрее SSD. Это объясняет, почему кэширование критично для производительности.
Масштабы времени
Эта таблица помогает интуитивно понять разницу в скорости операций:
| Операция | Время | Человеческий масштаб |
|---|---|---|
| Чтение L1 кэша | 1 нс | 1 секунда |
| Чтение L2 кэша | 4 нс | 4 секунды |
| Чтение RAM | 100 нс | 1.5 минуты |
| Чтение SSD | 100 мкс | 1.5 дня |
| Чтение HDD | 5 мс | 2.5 месяца |
| Сеть (внутри DC) | 0.5 мс | 2.5 недели |
| Сеть (межконтинентальная) | 150 мс | 5 лет |
Summary
Если бы операции в компьютере происходили в человеческом масштабе, чтение с HDD заняло бы 2.5 месяца, а сетевой запрос в другой континент - 5 лет. Это объясняет, почему кэширование и локальность данных так важны.
Стоимость хранения
| Тип хранения | Стоимость за ГБ/месяц |
|---|---|
| RAM | $3-5 |
| SSD | $0.10-0.20 |
| HDD | $0.01-0.02 |
| S3 Standard | $0.023 |
| S3 Glacier | $0.004 |
Пример расчёта для интервью:
“Наш мессенджер генерирует 200 ГБ текстовых сообщений в день и 40 ТБ медиа. За год - 73 ТБ текста и 14.6 ПБ медиа. Если хранить текст в SSD (11 000/мес. Медиа в S3 Standard (336 000/мес. Итого ~$350 000/мес только на хранение.”
Important
На интервью не нужно знать точные цены, но понимание порядка величин (RAM в 100 раз дороже SSD, SSD в 10 раз дороже HDD/S3) помогает обосновывать архитектурные решения.
Network Policy
На уровне System Design интервью Network Policy - это не настройка YAML, а понимание принципов сегментации сети.
Ключевые концепции
Микросегментация:
- Разделение сети на маленькие сегменты
- Каждый сервис находится в своём сегменте
- Трафик между сегментами контролируется явно
Zero Trust:
- Никогда не доверяй, всегда проверяй
- Каждое соединение аутентифицируется
- Даже внутри датацентра трафик проверяется
K8s NetworkPolicy:
- Определяет, какие pod’ы могут общаться друг с другом
- Ingress rules: кто может обращаться К этому pod’у
- Egress rules: куда этот pod может обращаться
- Default deny: блокировать весь трафик, кроме явно разрешённого
AWS Security Groups:
- Stateful firewall на уровне инстанса
- Inbound rules: разрешить трафик от определённых источников
- Outbound rules: разрешить трафик к определённым назначениям
Service Mesh (Istio / Linkerd):
- mTLS между сервисами
- Политики трафика на уровне сервисов
- Observability: кто с кем общается
Info
На интервью достаточно сказать: “Я бы использовал микросегментацию сети с принципом zero trust. В Kubernetes это NetworkPolicy с default deny. В облаке - Security Groups. Для межсервисного взаимодействия - service mesh с mTLS.”
RBAC (Role-Based Access Control)
Ключевые концепции
Принцип наименьших привилегий:
- Давать минимум необходимых прав
- Каждый компонент имеет доступ только к тому, что ему нужно
- Если сервис читает из БД сообщений, у него нет прав на удаление пользователей
K8s RBAC:
- Role: определяет права внутри namespace
- ClusterRole: определяет права во всём кластере
- RoleBinding: связывает Role с пользователями / группами / service accounts
- ServiceAccount: идентификация для pod’ов
IAM (AWS / Azure / GCP):
- Policies: JSON-документы, определяющие права
- Roles: принимаются сущностями (пользователи, сервисы, EC2 инстансы)
- Groups: набор пользователей с общими правами
ABAC (Attribute-Based Access Control):
- Доступ на основе атрибутов (отдел пользователя, время суток, локация)
- Более гибкий, чем RBAC, но сложнее в управлении
Info
На интервью достаточно сказать: “Я бы применил принцип наименьших привилегий. В Kubernetes - RBAC с отдельными ServiceAccount для каждого сервиса. В облаке - IAM roles с narrowly scoped policies.”
Почему это важно на интервью
Интервьюер оценивает:
- Понимаете ли вы реальные ограничения (не живёте в мире абстракций)
- Можете ли вы обосновать выбор технологии с точки зрения стоимости
- Знаете ли you, как физическая инфраструктура влияет на архитектуру
Как естественно внедрить в разговор:
“Для базы данных я выбираю SSD, потому что latency в 100 мкс против 5 мс у HDD - критично для нашего SLA в 200 мс.”
“Шардирование по chat_id означает, что hot chats создадут hotspot на одном шарде. В реальности это означает, что один сервер в стойке будет нагружен сильнее остальных.”
“Multi-region replication добавляет latency 50-200 мс между континентами. Поэтому мы используем eventual consistency для межрегиональной синхронизации, а strong consistency - внутри региона.”
“Хранение 14.6 ПБ медиа в S3 обойдётся в ~$336 000/мес. Если использовать SSD - это был бы astronomical cost. Поэтому hot медиа в CDN, а архив - в S3 Glacier.”
Разбор: URL Shortener
Этот разбор демонстрирует контраст с WhatsApp. Если WhatsApp - write-heavy система реального времени, то URL Shortener - read-heavy система с простой архитектурой и другими trade-off’ами.
Фаза 1: Требования
Функциональные:
- Создание короткого alias для длинного URL
- Перенаправление по короткому alias на оригинальный URL
- Кастомные alias (опционально)
- Срок действия ссылки (опционально)
Нефункциональные:
- Latency: менее 100 мс на перенаправление
- Доступность: 99.9%
- Масштаб: 100 миллионов новых URL в месяц, 10 миллиардов перенаправлений в месяц
Info
Контраст с WhatsApp: URL Shortener создаёт мало данных (100M/мес), но читает много (10B/мес). WhatsApp создаёт много данных (2B/день) и читает много (20B/день), но соотношение read/write ближе к 10:1.
Фаза 2: Оценка масштаба
Новых URL в месяц: 100 000 000
Write QPS: 100M ÷ (30 × 86400) ≈ 40
Перенаправлений в месяц: 10 000 000 000
Read QPS: 10B ÷ (30 × 86400) ≈ 4 000
Средний размер URL: 500 байт
Хранилище в месяц: 100M × 500B = 50 ГБ
Хранилище в год: ~600 ГБ
Important
Контраст с WhatsApp: Write QPS всего 40 (против 23 000), read QPS 4 000 (против 230 000). Но соотношение read/write = 100:1 (против 10:1 у WhatsApp). Это кардинально меняет архитектуру.
Фаза 3: Высокоуровневый дизайн
Архитектура:
┌─────────┐ ┌───────────────┐ ┌─────────────┐ ┌──────────┐
│ Client │────→│ Load Balancer │────→│ App Server │────→│ Cache │
└─────────┘ └───────────────┘ └─────────────┘ │ (Redis) │
└────┬─────┘
│
↓
┌──────────┐
│ Database │
│ (SQL or │
│ NoSQL) │
└──────────┘
API:
| Method | Endpoint | Описание |
|---|---|---|
| POST | /shorten | Создать короткий URL |
| GET | /{short_code} | Перенаправить на оригинальный URL |
Модель данных:
url_mappings
- short_code (PK, строка 7 символов)
- original_url (строка, индексировано)
- created_at
- expires_at (опционально)
- click_count
Фаза 4: Углубление
Тема 1: Генерация коротких ссылок
Три подхода:
| Подход | Принцип | Плюсы | Минусы |
|---|---|---|---|
| Hash-based | MD5/SHA-256 от URL, первые 7 символов | Детерминировано, одинаковый URL → одинаковый short code | Коллизии, предсказуемо |
| Base62 encoding | Автоинкремент ID в base62 (0-9, a-z, A-Z) | Просто, компактно | Предсказуемо, можно угадать следующую ссылку |
| Random string | Случайные 7 символов base62 | Непредсказуемо, 3.5 триллиона комбинаций | Нужна проверка коллизий |
Important
Выбор: Random string 7 символов base62 = 62^7 ≈ 3.5 триллиона комбинаций. При 100M URL/мес коллизии практически невозможны. Это самый популярный подход в production.
Контраст с WhatsApp:
- WhatsApp: сообщения уникальны по времени + sender (нет коллизий)
- URL Shortener: короткие коды должны быть уникальны (нужна проверка коллизий)
Тема 2: Оптимизация чтения
Кэш-first архитектура:
- Redis с TTL (например, 24 часа для популярных ссылок)
- Cache hit ratio: 95%+
- Cache miss: запрос в БД, запись в кэш
Почему это работает:
- 95%+ перенаправлений идут на популярные ссылки
- Redis даёт latency < 1 мс
- БД используется только для 5% запросов
Info
Контраст с WhatsApp: WhatsApp тоже использует кэш (Redis для последних сообщений), но там кэш менее эффективен, потому что каждый пользователь читает разные сообщения. URL Shortener имеет высокую локальность популярных ссылок.
Тема 3: Выбор базы данных
Trade-off SQL vs NoSQL:
| Аспект | SQL (PostgreSQL) | NoSQL (Cassandra) |
|---|---|---|
| Консистентность | ACID, strong consistency | Eventual consistency |
| Масштабирование | Vertical + read replicas | Horizontal шардирование |
| Запросы | Сложные запросы, JOIN’ы | Простые ключ-значение |
| Подходит для | < 10K QPS | > 10K QPS |
Ключевой вопрос:
“URL Shortener требует strong consistency - мы не можем позволить двум разным URL иметь одинаковый short code. Это аргумент за SQL. Но с 4000 read QPS и кэшированием мы можем использовать PostgreSQL с read replicas.”
Important
Выбор: PostgreSQL с read replicas + Redis кэш. При необходимости масштабирования - шардирование по short_code prefix.
Контраст с WhatsApp:
- URL Shortener: strong consistency критична (нет дубликатов short codes)
- WhatsApp: eventual consistency допустима (сообщения дойдут через секунду)
- URL Shortener: read-heavy (100:1), оптимизация на чтение
- WhatsApp: write-heavy (10:1), оптимизация на запись
Фаза 5: Завершение
Аналитика:
- Отслеживание кликов (click_count в БД)
- Географическое распределение кликов
- Популярные ссылки
Очистка:
- Удаление просроченных ссылок
- Архивация старых записей
- Компактный формат для архива
Rate limiting:
- Ограничение создания ссылок с одного IP
- Защита от злоупотреблений
Сравнительная таблица: WhatsApp vs URL Shortener
| Аспект | URL Shortener | |
|---|---|---|
| Тип нагрузки | Write-heavy (10:1) | Read-heavy (100:1) |
| Консистентность | Eventual consistency допустима | Strong consistency обязательна |
| Сложность | Высокая (real-time, sync, media) | Низкая (простое перенаправление) |
| Ключевой компонент | WebSocket, Message Queue | Кэш (Redis) |
| База данных | NoSQL (шардирование) | SQL (ACID) |
| Latency требование | < 200 мс | < 100 мс |
| Соотношение R/W QPS | 230K / 23K | 4K / 40 |
Summary
Эти два примера показывают, как одинаковый пятифазный фреймворк применяется к совершенно разным системам. WhatsApp требует сложной архитектуры реального времени. URL Shortener - простой, но требует оптимизации чтения и strong consistency. На интервью важно показать, что вы понимаете специфику задачи и адаптируете архитектуру под неё.
Подготовка к интервью
Чек-лист подготовки
Основные темы для повторения
-
Масштабирование
- Horizontal vs vertical scaling
- Шардирование (sharding) - по какому ключу, какие проблемы
- Репликация - master-slave, master-master, quorum
- CAP теорема - когда выбирать consistency, когда availability
-
Базы данных
- SQL vs NoSQL - trade-off’ы, когда что использовать
- Индексы - B-tree, hash, inverted
- Транзакции - ACID, isolation levels
- Нормализация vs денормализация
-
Кэширование
- Cache aside, read-through, write-through, write-behind
- Cache eviction policies - LRU, LFU, TTL
- Cache invalidation strategies
- Distributed caching - Redis, Memcached
-
Сообщения и очереди
- Message brokers - Kafka, RabbitMQ, SQS
- Publish-subscribe vs point-to-point
- Гарантии доставки - at-most-once, at-least-once, exactly-once
- Backpressure и circuit breaker
-
Сети
- HTTP/1.1 vs HTTP/2 vs HTTP/3
- WebSocket vs Server-Sent Events vs Long Polling
- Load balancing - round-robin, least connections, consistent hashing
- CDN - как работает, когда использовать
-
Безопасность
- HTTPS / TLS - как работает handshake
- OAuth 2.0 / JWT - аутентификация и авторизация
- SQL injection, XSS, CSRF - защита
- Rate limiting - token bucket, leaky bucket
-
Микросервисы
- Service discovery - Consul, Eureka, K8s DNS
- API Gateway - routing, rate limiting, auth
- Inter-service communication - REST, gRPC, messaging
- Service mesh - Istio, Linkerd
-
Наблюдаемость
- Метрики - latency, throughput, error rate
- Логирование - структурированные логи, уровни
- Трейсинг - distributed tracing, Jaeger, Zipkin
- Alerting - когда и как оповещать
Практические задачи
Потренируйтесь на этих системах:
- WhatsApp / Telegram - мессенджер (write-heavy, real-time)
- URL Shortener - сервис коротких ссылок (read-heavy, simple)
- Twitter / News Feed - лента новостей (read-heavy, fan-out)
- Uber / Lyft - сервис заказа такси (real-time, geospatial)
- Netflix / YouTube - видеостриминг (bandwidth-heavy, CDN)
- Amazon / E-commerce - интернет-магазин (transactions, search)
- Google Docs - совместное редактирование (real-time collaboration)
- Rate Limiter - ограничение запросов (distributed, accurate)
Info
Для каждой задачи пройдите все 5 фаз: требования → оценка → HLD → deep dive → wrap-up. Потратьте 45-60 минут, как на реальном интервью.
Ресурсы
Книги:
- “Designing Data-Intensive Applications” by Martin Kleppmann (DDIA) - обязательна
- “System Design Interview” by Alex Xu - структура интервью
- “Grokking the System Design Interview” - краткий обзор
Веб-сайты:
- System Design Primer (GitHub) - отличная отправная точка
- ByteByteGo (YouTube) - визуальные объяснения
- DesignGurus.io - структурированные курсы
Практика:
- Pramp - бесплатные mock interviews
- Interviewing.io - mock interviews с инженерами
- Практикуйтесь с другом - один интервьюер, другой кандидат
Стратегия mock interview
- Найдите партнёра - друг, коллега или сервис вроде Pramp
- Выберите задачу - из списка выше или придумайте сами
- Установите таймер - 60 минут, без перерывов
- Делайте заметки - что пошло хорошо, что улучшить
- Получите feedback - попросите партнёра оценить по 4 компетенциям
Типичные ошибки
Ошибка 1: Начать решать без уточнения требований
Почему это проблема: Вы проектируете систему для неправильного масштаба или упускаете критичные требования. Интервьюер специально даёт минимум информации, чтобы проверить, зададите ли вы вопросы.
Как избежать: Всегда начинайте с 3-5 уточняющих вопросов. Даже если требования кажутся очевидными, уточните масштаб и приоритеты.
Что сказать:
“Прежде чем начать проектировать, хочу уточнить несколько моментов. Для скольких пользователей мы проектируем? Какие функции обязательны? Есть ли ограничения по latency?”
Ошибка 2: Игнорировать нефункциональные требования
Почему это проблема: Доступность 99.9% и 99.999% - это разные архитектуры. eventual consistency и strong consistency - разные решения. Без этих требований вы не можете обосновать выбор технологий.
Как избежать: Явно спросите про:
- Availability (99.9%, 99.99%, 99.999%)
- Consistency (strong, eventual, causal)
- Latency (p50, p95, p99)
- Throughput (QPS, bandwidth)
Ошибка 3: Переусложнять с первого шага
Почему это проблема: Сложная архитектура из 15 компонентов трудно объяснить и отлаживать. Интервьюер оценивает процесс мышления, а не количество компонентов. Переусложнение показывает неумение приоритизировать.
Как избежать: Начинайте с 3-5 компонентов. Усложняйте только там, где это обосновано. Правило: “Простое решение, которое работает, лучше сложного, которое тоже работает.”
Ошибка 4: Не обсуждать trade-off’ы
Почему это проблема: Каждое решение имеет цену. Если вы не обсуждаете альтернативы, интервьюер не видит глубины вашего понимания. “Я выбираю NoSQL” без объяснения почему - недостаточно.
Как избежать: Для каждого ключевого решения предлагайте 2-3 альтернативы:
“Для хранения можно использовать PostgreSQL или Cassandra. PostgreSQL даёт ACID и сложные запросы, но сложнее масштабировать. Cassandra легко шардировать, но eventual consistency может быть проблемой. Я выбираю PostgreSQL, потому что strong consistency критична для этой задачи.”
Ошибка 5: Молчать или думать про себя
Почему это проблема: Интервьюер не видит ваш процесс мышления. Вы можете прийти к правильному ответу, но не получить credit за путь. Молчание на 5 минут - красный флаг.
Как избежать: Думайте вслух. Объясняйте каждый шаг. Рисуйте на доске или в редакторе. Даже если вы не уверены, скажите: “Я думаю над этим. Вот варианты, которые рассматриваю…”
Ошибка 6: Не оценивать масштаб
Почему это проблема: Без расчётов вы не можете обосновать выбор технологий. SQL может быть нормально для 1000 пользователей, но не для 100 миллионов. Оценка масштаба - основа всех последующих решений.
Как избежать: Всегда делайте back-of-the-envelope расчёты. Показывайте их на доске. Объясняйте assumptions.
Ошибка 7: Забывать про мониторинг и отказы
Почему это проблема: Production система без мониторинга - это чёрный ящик. Без плана отказов - это система, которая упадёт при первой проблеме. Интервьюер хочет видеть, что вы думаете о production.
Как избежать: Завершайте интервью обсуждением:
- Какие метрики мониторить (latency, error rate, throughput)
- Какие алерты настроить
- Что делать при отказе БД, сервера, датацентра
Ошибка 8: Защищать ошибочное решение
Почему это проблема: Интервьюер может указывать на реальные проблемы. Защита “до последнего” показывает негибкость и неумение слушать feedback.
Как избежать: Будьте открыты к корректировкам:
“Вы правы, этот подход создаёт bottleneck при пиковой нагрузке. Давайте пересмотрим - вместо одного master’а используем шардирование.”
Ошибка 9: Не спрашивать направления у интервьюера
Почему это проблема: Интервьюер может быть заинтересован в конкретной области. Если вы углубляетесь не туда, теряете время на нерелевантные детали.
Как избежать: Спрашивайте:
“В какую часть системы стоит углубиться?” “Что для вас наиболее интересно в этом дизайне?”
План подготовки на 2 недели
Неделя 1: Теория
| День | Тема | Действие |
|---|---|---|
| 1 | Масштабирование | Прочитать главу о масштабировании в DDIA. Повторить CAP теорему. |
| 2 | Базы данных | Прочитать про SQL vs NoSQL, индексы, шардирование. |
| 3 | Кэширование | Изучить стратегии кэширования, eviction policies. |
| 4 | Сообщения | Изучить Kafka, RabbitMQ, гарантии доставки. |
| 5 | Сети | Повторить HTTP/2, WebSocket, load balancing, CDN. |
| 6 | Безопасность | Повторить TLS, OAuth, JWT, основные атаки. |
| 7 | Микросервисы | Изучить service discovery, API gateway, service mesh. |
Неделя 2: Практика
| День | Задача | Действие |
|---|---|---|
| 8 | Пройти все 5 фаз самостоятельно, записать на видео. | |
| 9 | URL Shortener | Пройти все 5 фаз, сравнить с WhatsApp. |
| 10 | Потренироваться на feed системе. | |
| 11 | Uber | Потренироваться на geospatial задаче. |
| 12 | Mock interview 1 | С другом или на Pramp. Получить feedback. |
| 13 | Netflix | Потренироваться на стриминговой системе. |
| 14 | Mock interview 2 | С другом или на Pramp. Сравнить прогресс. |
Important
Ключ к успеху - регулярная практика. Одно интервью в неделю лучше, чем 10 интервью за один день перед собеседованием. Процесс мышления вырабатывается через повторение.
Заключение
System Design интервью - это навык, который развивается через практику. Пятифазный фреймворк (требования → оценка → HLD → deep dive → wrap-up) даёт структуру, в рамках которой вы можете демонстрировать своё мышление. Два разбора в этой заметке - WhatsApp и URL Shortener - показывают, как один и тот же фреймворк применяется к разным типам систем с разными trade-off’ами.
Ключевые принципы, которые стоит запомнить:
-
Начинайте с вопросов, а не с решения. Уточнение требований - самый важный первый шаг.
-
Показывайте расчёты. Back-of-the-envelope оценки демонстрируют понимание масштаба.
-
Обсуждайте trade-off’ы. Для каждого решения предлагайте альтернативы и объясняйте выбор.
-
Думайте вслух. Интервьюер оценивает процесс, а не только результат.
-
Завершайте обсуждением production. Мониторинг, отказы, масштабирование - всё это показывает зрелость мышления.
Полезные ссылки
- System Design - техническая база - полное руководство по системному дизайну
- Микросервисы - паттерны микросервисной архитектуры
- Сети - сетевые основы
- Kubernetes Entities - сущности Kubernetes
- Хранение данных - работа с дисками и хранилищами
Important
Практика важнее теории. Потратьте 45-60 минут на полный проход хотя бы для трёх разных систем. Запишите себя на видео или попросите друга сыграть роль интервьюера. Каждое практическое интервью делает вас увереннее.