Интервью по System Design. youtube
Сегодня мы разберём собеседование по проектированию системы видеохостинга, в ходе которого кандидат под руководством интервьюера последовательно определил функциональные и нефункциональные требования, оценил нагрузку и объёмы данных, а затем предложил микросервисную архитектуру с компонентами для загрузки, транскодирования, хранения и отдачи видео через CDN. Интервьюер активно направлял диалог, проверяя глубину понимания кандидатом принципов масштабирования, выбора технологий и балансировки нагрузки в распределённой системе.
Вопрос 1. Какие функциональные и нефункциональные требования предъявляются к сервису загрузки и просмотра видео (аналог YouTube)?
Таймкод: 00:01:03
Ответ собеседника: Правильный. Основные функции — загрузка и просмотр видео. Дополнительно: лайки, дизлайки, комментарии, плейлисты, шаринг, приватные видео. Для MVP достаточно загрузки и просмотра, остальное — в последующих версиях. Нефункциональные требования: персистентность (гарантия хранения загруженных видео), быстрая загрузка и воспроизведение, высокая доступность сервиса несмотря на сбои.
Правильный ответ:
Ответ кандидата корректен и хорошо структурирован. Для полноты картины стоит расширить оба раздела.
Функциональные требования:
Ядро (MVP):
- Загрузка видео с клиента (поддержка различных форматов: MP4, AVI, MOV, WebM и др.)
- Воспроизведение видео в браузере (адаптивный стриминг)
- Регистрация и аутентификация пользователей
- Профиль канала с загруженными видео
Расширенный функционал:
- Система реакций: лайки, дизлайки, избранное
- Комментарии с поддержкой ветвления дискуссий
- Плейлисты и очереди воспроизведения
- Шаринг видео через ссылки и встраивание (embed)
- Настройки приватности: публичные, по ссылке, приватные видео
- Подписки на каналы с уведомлениями о новых видео
- Поиск и рекомендации
- Система монетизации (для платформ с рекламой)
- Модерация контента и система жалоб
- Субтры и автоматическая генерация субтитров
- Аналитика для авторов (просмотры, аудитория, вовлечённость)
- Трансляции в реальном времени (live streaming)
- Shorts / короткие видео
Нефункциональные требования:
Масштабируемость:
- Горизонтальное масштабирование для поддержки миллионов одновременных просмотров
- Эффективная обработка пиковых нагрузок (вирусные видео, события)
- Архитектура, позволяющая масштабировать компоненты независимо
Производительность:
- Минимальное время начала воспроизведения (time-to-first-frame) — целевое значение менее 2 секунд
- Адаптивный битрейт-стриминг (ABR) для автоматической подстройки качества под скорость соединения пользователя
- Эффективная обработка видео (транскодирование в несколько разрешений и битрейтов)
- Оптимизация загрузки: resumable upload, параллельная загрузка чанков
Доступность и отказоустойчивость:
- Целевая доступность 99.99% (four nines) для критичных компонентов
- Географическое распределение серверов (CDN) для снижения латентности
- Репликация данных и автоматическое переключение при сбоях
- Graceful degradation — при отказе некритичных сервисов ядро продолжает работать
Персистентность и надёжность:
- Гарантия сохранности загруженного контента (репликация видеофайлов, erasure coding)
- Целостность метаданных и пользовательских данных
- Резервное копирование и возможность восстановления
Безопасность:
- Защита от несанкционированного доступа к приватному контенту
- DRM (Digital Rights Management) для защищённого контента
- Защита от DDoS-атак
- Валидация и санитизация загружаемых файлов (защита от вредоносного контента)
Наблюдаемость:
- Метрики производительности на каждом этапе (загрузка, транскодирование, доставка)
- Распределённая трассировка запросов
- Централизованное логирование и алертинг
Стоимость:
- Оптимизация затрат на хранение и трафик (иерархическое хранение, горячее/холодное)
- Эффективное использование ресурсов транскодирования
Вопрос 2. Нужно ли хранить видео в различных форматах/разрешениях и какие плюсы и минусы у транскодирования?
Таймкод: 00:04:00
Ответ собеседника: Правильный. Рекомендуется раскодировать исходное видео в несколько форматов (360p, 720p, 1080p и т.д.). Плюсы: гибкость в обеспечении QoS при плохом канале — можно уменьшать качество на лету; при хорошем канале пользователь получает видео в высоком качестве. Минусы: увеличивается объём занимаемого места на хранилище.
Правильный ответ:
Ответ кандидата в целом верный. Дополним его деталями для полноты.
Необходимость хранения нескольких форматов/разрешений:
Да, это стандартная практика для видеоплатформ. Технология называется Adaptive Bitrate Streaming (ABR). Видео транскодируется в набор разрешений и битрейтов (ladder):
- 2160p (4K) — ~15-25 Mbps
- 1080p — ~5-8 Mbps
- 720p — ~2.5-5 Mbps
- 480p — ~1-2.5 Mbps
- 360p — ~0.5-1 Mbps
- 240p — ~0.3-0.5 Mbps
Каждое разрешение нарезается на сегменты (чанки) длительностью 2-10 секунд, и клиент динамически переключается между ними в зависимости от текущей скорости соединения.
Форматы контейнеров и кодеки:
Помимо разрешений, важно хранить видео в нескольких форматах:
- HLS (HTTP Live Streaming) — сегменты в формате
.tsили.mp4, манифест.m3u8(Apple-экосистема, широкая поддержка) - DASH (Dynamic Adaptive Streaming over HTTP) — сегменты
.m4s, манифест.mpd(открытый стандарт) - Кодеки: H.264 (совместимость), H.265/HEVC (эффективность), VP9 и AV1 (открытые, экономия трафика)
Плюсы транскодирования:
- Адаптивность к каналу — плавное переключение качества без буферизации, пользователь всегда получает оптимальное качество для своего соединения
- Совместимость устройств — разные устройства поддерживают разные кодеки и разрешения; набор вариантов покрывает весь спектр
- Экономия трафика — мобильные пользователи с лимитным интернетом получают меньший битрейт, что снижает их расходы и повышает удержание
- CDN-эффективность — популярные разрешения кэшируются на edge-серверах, снижая нагрузку на origin
- Снижение нагрузки на клиент — мобильные устройства не тратят ресурсы на декодирование 4K, если экран не поддерживает такое разрешение
Минусы транскодирования:
- Увеличение объёма хранилища — каждый вариант занимает место; при наличии 5-6 разрешений общий объём может быть в 3-5 раз больше исходного файла
- Вычислительные затраты — транскодирование ресурсоёмко, особенно для 4K и длительных видео; требуются GPU-ускорители или выделенные фермы
- Задержка публикации — после загрузки видео недоступно до завершения транскодирования; для длинных видео это может занимать минуты или часы
- Сложность инфраструктуры — необходим оркестратор задач транскодирования, очереди, мониторинг, повторные попытки при сбоях
- Финансовые затраты — стоимость хранения, вычислений и CDN-трафика растёт кратно
Оптимизации:
- Just-in-time транскодирование — генерировать разрешения по запросу, а не для каждого видео; экономия ресурсов для непопулярного контента
- Перцептивное кодирование — использовать per-title encoding, при котором битрейт подбирается индивидуально под сложность контента (анимация требует меньше битрейта, чем динамичный экшен)
- Холодное хранилище — редко запрашиваемые разрешения перемещать в дешёвое хранилище (S3 Glacier и аналоги)
- Прогрессивная обработка — сначала публиковать видео в низком разрешении (для быстрого доступа), затем фоново генерировать высокие
Вопрос 3. Какова географическая аудитория сервиса и с каких устройств пользователи будут получать доступ?
Таймкод: 00:05:50
Ответ собеседника: Правильный. Сервис рассчитан на весь мир. Пользователи будут получать доступ с различных устройств: смартфоны, планшеты, ноутбуки, компьютеры, Smart TV.
Правильный ответ:
Ответ кандидата корректен, но для полноценного проектирования системы необходимо детализировать оба аспекта.
Географическая аудитория:
При проектировании глобального сервиса важно учитывать региональные особенности:
- Северная Америка и Европа — высокая скорость интернета, доминирование десктопа и Smart TV, высокие требования к качеству (4K), строгие требования к персональным данным (GDPR, CCPA)
- Азиатско-Тихоокеанский регион — крупнейшая аудитория, мобильный трафик доминирует (70-80%), разнообразие скоростей соединения, необходимость поддержки локальных языков и кодировок
- Латинская Америка, Африка, Ближний Восток — преимущественно мобильный доступ, низкая средняя скорость интернета, критична поддержка низких разрешений (240p-360p), экономия трафика — ключевой фактор удержания
Региональные особенности влияют на архитектуру: размещение дата-центров, CDN-провайдеров, соблюдение локального законодательства (хранение данных в пределах юрисдикции), поддержка локальных способов оплаты и языков.
Устройства доступа:
Мобильные устройства (iOS, Android):
- Доминирующий канал в большинстве регионов (60-80% трафика)
- Ограничения по трафу, батарее, размеру экрана
- Необходимость нативных приложений с поддержкой фонового воспроизведения, Picture-in-Picture, загрузки офлайн
- Разнообразие экранов и аппаратных декодеров
Десктоп (браузеры):
- Широкий спектр браузеров и версий
- Поддержка HTML5 Video, Media Source Extensions (MSE) для ABR
- Высокие ожидания по качеству (1080p-4K)
- Поддержка горячих клавиш, полноэкранного режима
Smart TV и стриминговые устройства (Roku, Apple TV, Chromecast, Fire TV, игровые консоли):
- Растущий сегмент с высоким средним временем просмотра
- Ограниченные вычислительные ресурсы, специфические SDK
- Управление через пульт (навигация без мыши)
- Поддержка 4K, HDR, Dolby Vision, Dolby Atmos
Планшеты:
- Промежуточный сегмент между мобильными и десктопом
- Часто используются для потребления контента дома по Wi-Fi
Влияние на архитектуру:
- Необходимость поддержки нескольких протоколов стриминга (HLS, DASH) для совместимости со всеми устройствами
- Разные форматы рекламы (pre-roll, mid-roll, overlay) для разных платформ
- Адаптивный UI/UX под каждый форм-фактор
- Тестирование на реальных устройствах и эмуляторах
- Разные стратегии кэширования и предзагрузки для мобильных и десктопных клиентов
Вопрос 4. Каковы ключевые числовые характеристики сервиса: количество ежедневных активных пользователей, среднее время просмотра, процент загружающих видео, средний объём загрузки? Какой объём хранилища потребуется в день?
Таймкод: 00:06:55
Ответ собеседника: Правильный. Приняты следующие допущения: 20 млн ежедневных активных пользователей, в среднем 50 минут просмотра в день. 0,1% пользователей (20 000) загружают видео, каждый загружает в среднем одно часовое видео в 4К — примерно 100 ГБ. Итого: 20 000 × 100 ГБ = 2 000 000 ГБ = 2000 ТБ ≈ 2 петабайта в день.
Правильный ответ:
Ответ кандидата в целом верен по подходу и допущениям. Расчёт корректен: 20 000 × 100 ГБ = 2 000 000 ГБ = 2 ПБ/день. Допущения реалистичны и хорошо обоснованы. Дополним анализ для полноты.
Допущения и их обоснование:
Ежедневные активные пользователи (DAU): 20 млн
- Реалистичная цифра для крупного, но не доминирующего сервиса (YouTube ~2 млрд DAU, региональные платформы — 10-50 млн)
Среднее время просмотра: 50 минут/день
- Соответствует индустриальным метрикам (YouTube ~40-60 мин, TikTok ~50-60 мин)
- Влияет на расчёт исходящего трафика и нагрузку на CDN
Процент загружающих: 0,1%
- Типичное соотношение creator/viewer для платформ с пользовательским контентом
- Из 20 млн DAU = 20 000 загрузок в день
Средний размер загрузки: 100 ГБ (1 час 4K)
- 4K видео с битрейтом ~20-25 Mbps даёт примерно 9-11 ГБ в час; при более высоком битрейте или исходнике без сжатия — до 100 ГБ вполне реалистично
- На практике исходники варьируются от 1 ГБ (сжатое 1080p) до сотен ГБ (профессиональное 4K/8K raw)
Расчём хранилища:
- 20 000 загрузок × 100 ГБ = 2 000 000 ГБ = 2 ПБ/день
- С учётом транскодирования в 5 разрешений (множитель ×3-5): 6-10 ПБ/день суммарного хранилища
- За год: ~2-4 ЭБ (экзабайт) нового контента
Дополнительные метрики для проектирования:
- Пиковый RPS на загрузку: 20 000 загрузок за ~8 часов пиковой активности ≈ ~0,7 RPS в среднем, с пиками до 5-10 RPS
- Пиковый RPS на просмотр: 20 млн × 50 мин / 86400 сек ≈ ~11 500 одновременных стримов в среднем; с учётом пикового коэффициента ×3 = ~35 000 одновременных стримов
- Исходящий трафик CDN: 11 500 × 5 Mbps (средний битрейт) ≈ 57,5 Gbps в среднем; пиковый ~170 Gbps
- Количество запросов метаданных: порядок сотен тысяч RPS (поиск, рекомендации, лента)
Оптимизации хранилища:
- Per-title encoding для снижения битрейта без потери качества
- Хранение исходника + производных разрешений; при необходимости — только исходник с JIT-транскодированием
- Иерархическое хранение: горячее (SSD) для популярного контента, холодное (HDD/S3) для редко запрашиваемого
- Дедупликация контента (для борьбы с повторными загрузками)
Вопрос 5. Как долго будет храниться загруженный контент и как планировать масштабирование хранилища?
Таймкод: 00:12:33
Ответ собеседника: Правильный. Видео будет храниться бессрочно. Можно заложить хранилище на определённый горизонт (например, 10 лет) и по мере заполнения горизонтально масштабироваться — заранее выкупать дополнительные мощности. Резервировать место рациональнее часто, например раз в год, чтобы не платить за неиспользуемое хранилище на 9 лет вперёд.
Правильный ответ:
Ответ кандидата содержит правильные идеи. Дополним его системным подходом к планированию хранения.
Политика хранения контента:
Бессрочное хранение по умолчанию — стандартный подход для крупных платформ. Однако на практике существуют нюансы:
- Контент удаляется по запросу автора, по жалобам (DMCA, нарушение правил), при блокировке аккаунта
- Для неактивных аккаунтов может применяться политика архивации (перемещение в холодное хранилище)
- Некоторые платформы вводят лимиты хранения для бесплатных аккаунтов
Стратегия масштабирования хранилища:
Горизонтальное масштабование:
- Использование распределённых объектных хранилищ (S3-совместимые, HDFS, Ceph)
- Шардирование по идентификатору видео или по времени загрузки
- Линейное наращивание ёмкости без downtime
Планирование ёмкости:
- Прогнозирование роста на основе метрик: количество загрузок/день, средний размер, коэффициент транскодирования
- Закупка ёмкости квартально или ежемесячно на основе тренда, а не на годы вперёд
- Использование гибридной модели: собственное хранилище для горячего контента + облако для эластичного масштабирования и холодного хранения
Иерархическое хранение (Storage Tiering):
- Hot tier (SSD/NVMe): последние загрузки и популярный контент, высокий IOPS, минимальная латентность
- Warm tier (HDD): контент средней популярности, сбалансированная стоимость и производительность
- Cold tier (S3 Glacier, tape): редко запрашиваемый контент, минимальная стоимость хранения, высокая латентность доступа
- Автоматическое перемещение между тирами на основе паттернов доступа (lifecycle policies)
Оптимизация затрат:
- Дедупликация: обнаружение идентичных или похожих видео для исключения дубликатов
- Erasure coding вместо полной репликации: снижение накладных расходов с 3× до 1.5×
- Per-title encoding: оптимизация битрейта под конкретный контент, экономия 20-40% объёма
- JIT-транскодирование: генерация разрешений по запросу для непопулярного контента
Мониторинг и прогнозирование:
- Дашборды с текущим заполнением, трендом роста, прогнозом исчерпания
- Автоматические алерты при достижении порогов (70%, 85%, 95%)
- Ежемесячный пересчёт прогноза на основе фактических метрик
Вопрос 6. Как спроектировать верхнеуровневую архитектуру процесса загрузки видео, включая метаданные, транскодирование и взаимодействие компонентов?
Таймкод: 00:22:50
Ответ собеседника: Правильный. Пользователь авторизован и приходит с токеном в API Gateway. API Gateway проверяет доступ, обращается к базе метаданных и создаёт запись, после чего отвечает пользователю, что он может загружать видео в отдельное blob-хранилище. После завершения загрузки upload-сервис через брокер сообщений формирует задачи для воркеров-транскодеров, каждый отвечает за свой формат. Воркеры забирают видео, транскодируют и обновляют запись в базе метаданных ссылками на результаты.
Правильный ответ:
Ответ кандидата демонстрирует хорошее понимание архитектуры. Дополним деталями и расширим схему.
Верхнеуровневая архитектура загрузки видео:
1. Инициализация загрузки:
Клиент → API Gateway → Upload Service
POST /api/v1/videos/upload/init
Authorization: Bearer <token>
Body: {title, description, tags, visibility, content_type, file_size}
Upload Service:
- Валидирует запрос (размер файла, формат, квоты пользователя)
- Создаёт запись в Metadata DB со статусом
UPLOADING - Генерирует уникальный
video_id - Запрашивает у Storage Service presigned URL для прямой загрузки в объектное хранилище
- Возвращает клиенту:
video_id,upload_url,chunk_size,max_chunks
2. Загрузка файла:
Клиент → Object Storage (S3-совместимое) — напрямую, минуя серверную часть
Поддержка resumable upload:
- Файл разбивается на чанки (например, по 5-10 МБ)
- Каждый чанк загружается отдельным запросом
- При сбое — повторная загрузка только неудачных чанков
- После загрузки всех чанков — отправляется запрос на завершение
3. Уведомление о завершении загрузки:
Клиент → Upload Service: POST /api/v1/videos/{video_id}/upload/complete
Или Object Storage → Upload Service через event notification (S3 Event → SQS/SNS)
Upload Service:
- Верифицирует целостность файла (checksum, размер)
- Обновляет статус в Metadata DB на
PROCESSING - Публикует событие в Message Broker (Kafka/RabbitMQ/SQS)
4. Оркестрация транскодирования:
Transcoding Service (оркестратор):
- Подписан на очередь задач транскодирования
- Получает
video_idи ссылку на исходный файл - Определяет набор целевых форматов (ladder) на основе исходного разрешения и контента
- Создаёт N задач для Transcoding Workers (по одной на каждое разрешение)
- Отправляет задачи в отдельные очереди или с приоритетами
5. Транскодирование:
Transcoding Workers (горизонтально масштабируемые):
- Забирают задачу из очереди
- Скачивают исходный файл из Object Storage
- Транскодируют в целевое разрешение (FFmpeg, GPU-ускорение)
- Загружают результат в Object Storage
- Публикуют событие о завершении
6. Агрегация результатов:
Transcoding Service или отдельный Aggregation Service:
- Собирает события от всех воркеров
- По завершении всех форматов — обновляет Metadata DB: статус
READY, записывает ссылки на все варианты - Генерирует HLS/DASH манифесты
- Публикует событие
VideoReadyдля других сервисов (поиск, рекомендации, уведомления)
Схема метаданных:
videos:
- video_id (UUID)
- user_id
- title, description, tags[]
- visibility (public/unlisted/private)
- status (uploading/processing/ready/failed)
- original_url (ссылка на исходник в Object Storage)
- variants[]:
- resolution (360p, 720p, 1080p)
- codec (h264, h265, av1)
- bitrate
- url
- manifest_url (HLS/DASH)
- duration, file_size, created_at, updated_at
Паттерны и принципы:
- Асинхронность: транскодирование длительное — не блокируем клиента
- Event-driven: компоненты взаимодействуют через события, слабая связанность
- Горизонтальное масштабирование: воркеры транскодирования масштабируются независимо от остальной системы
- Idempotency: повторная обработка одного события не приводит к дублированию
- Dead letter queue: задачи, завершившиеся ошибкой, попадают в DLQ для повторной обработки или ручной модерации
- Circuit breaker: при сбое Object Storage или воркеров — остановка каскадных отказов
Вопрос 7. Как спроектировать архитектуру поиска и отдачи видео пользователю, включая роль CDN и кэширование популярного контента?
Таймкод: 00:30:59
Ответ собеседния: Правильный. Пользователь приходит в API Gateway с поисковым запросом или запросом списка видео. Запрос обрабатывается сервисом поиска, который ищет по метаданным. Из метаданных берутся ссылки на видео в blob-хранилище. Перед хранилищем ставится CDN для отдачи популярного контента, размещаясь ближе к геолокации пользователей.
Правильный ответ:
Ответ кандидата корректен. Дополним архитектуру деталями.
Архитектура поиска:
Поисковый запрос: Клиент → API Gateway → Search Service
Search Service:
- Принимает поисковый запрос, фильтры (дата, длительность, категория), параметры пагинации и сортировки
- Обращается к поисковому индексу (Elasticsearch/OpenSearch) для полнотекстового поиска по заголовкам, описаниям, тегам, имени автора
- Применяет ранжирование: релевантность, популярность, свежесть, персонализация
- Возвращает список
video_idс метаданными (без ссылок на видеофайлы)
Поисковый индекс:
- Elasticsearch/OpenSearch для полнотекстового поиска с поддержкой морфологии, автодополнения, исправления опечаток
- Данные индексируются через событие
VideoReadyпосле завершения транскодирования - Возможна отдельная индексация субтитров для поиска внутри видео
Персонализация и рекомендации:
- Отдельный Recommendation Service формирует персонализированные ленты
- Использует коллаборативную фильтрацию, контентные фичи, историю просмотров
- Кэширует результаты для каждого пользователя с TTL
Архитектура отдачи видео:
Просмотр видео: Клиент → API Gateway → Video Service
Video Service:
- Проверяет права доступа (приватность, возрастные ограничения, геоблокировка)
- Обращается к Metadata DB за информацией о видео
- Генерирует signed URL с ограниченным временем жизни для доступа к манифесту (HLS/DASH)
- Возвращает клиенту: метаданные видео, URL манифеста, информацию о доступных субтитрах
Воспроизведение: Клиент (видеоплеер) → CDN Edge → CDN Origin → Object Storage
- Клиент загружает манифест (
.m3u8/.mpd), содержащий ссылки на сегменты - Видеоплеер запрашивает сегменты через CDN
- CDN Edge кэширует сегменты; при попадании в кэш (cache hit) — отдаёт напрямую
- При промахе (cache miss) — CDN запрашивает сегмент у CDN Origin / Object Storage, кэширует и отдаёт клиенту
Роль CDN:
- Географическое распределение: edge-серверы в сотнях точек присутствия по всему миру, контент доставляется с ближайшего узла
- Снижение латентности: время до первого сегмента сокращается с сотен миллисекунд до единиц
- Снижение нагрузки на origin: 90-99% запросов контента обслуживается CDN, Object Storage получает минимальный трафик
- Абсорбция пиковых нагрузок: вирусные видео и события не влияют на origin-инфраструктуру
- Экономия стоимости: исходящий трафик из Object Storage значительно дороже, чем из CDN
Стратегия кэширования:
- Популярный контент: автоматически кэшируется на edge-серверах благодаря частым запросам
- Предзагрузка (prefetching): новые эпизоды популярных шоу, ожидаемые релизы загружаются на edge до публикации
- Cache TTL: для видеосегментов — длительный (дни/недели), для манифестов — короткий (минуты) для актуальности списка сегментов
- Cache invalidation: при удалении или замене видео — инвалидация кэша через API CDN
Адаптивный стриминг:
- Клиентский плеер мониторит скорость загрузки сегментов
- Автоматически переключается между разрешениями (ladder) в манифесте
- При ухудшении соединения — снижает битрейт; при улучшении — повышает
- Переключение происходит на границах сегментов, без прерывания воспроизведения
Signed URLs для безопасности:
- URL манифеста и сегментов содержат подпись и срок действия
- Предотвращает hotlinking и несанкционированный доступ
- Позволяет реализовать геоблокировку и проверку прав на уровне CDN
Вопрос 8. Почему выбрана микросервисная архитектура, а не монолит, и какие есть альтернативы?
Таймкод: 00:34:23
Ответ собеседника: Правильный. Сервисы stateless, данные хранятся в БД, поэтому легко балансировать нагрузку. В монолите функциональности пересекаются, сложнее поддерживать и деплоить. Микросервисы позволяют независимо масштабировать компоненты, упрощают мониторинг, и падение одного сервиса не тянет за собой другие.
Правильный ответ:
Ответ кандидата корректен. Дополним анализ более детальным сравнением.
Преимущества микросервисной архитектуры для видеоплатформы:
Независимое масштабирование:
- Компоненты системы имеют разные профили нагрузки: загрузка (write-heavy, пиковая), просмотр (read-heavy, постоянная), транскодирование (CPU/GPU-intensive, фоновая), поиск (latency-sensitive)
- Каждый сервис масштабируется независимо: воркеры транскодирования — по длине очереди, API-сервисы — по RPS, поиск — по объёму индекса
- Экономия ресурсов: не нужно масштабировать весь монолит из-за одного узкого места
Отказоустойчивость:
- Падение сервиса транскодирования не влияет на просмотр уже обработанных видео
- Падение сервиса рекомендаций — fallback на популярный контент
- Изоляция сбоев через circuit breaker, bulkhead pattern
Независимый деплой:
- Команды могут выпускать релизы своих сервисов без координации с другими
- Разные циклы разработки: критичные исправления — горячий деплой, новые фичи — по расписанию
- Снижение риска: баг в одном сервисе не затрагивает остальные
Технологическая гибкость:
- Сервис транскодирования — Go/C++ с GPU-ускорением
- Поиск — Java/Kotlin с Elasticsearch клиентом
- API Gateway — Go/Node.js
- Каждая команда выбирает оптимальный стек под свою задачу
Организационная масштабируемость:
- Отдельные команды владеют отдельными сервисами
- Чёткие границы ответственности через API-контракты
- Упрощение onboarding новых разработчиков
Альтернативы и сравнение:
Монолит:
- Проще на старте: один репозиторий, один деплой, отсутствие сетевых вызовов между компонентами
- Подходит для MVP и небольших команд (до 10-15 разработчиков)
- Проблемы при росте: время сборки, конфликты при мерже, невозможность изолировать сбои
- Переход от монолита к микросервисам возможен через паттерн Strangler Fig
Модульный монолит:
- Компромиссный вариант: один деплойный артефакт, но с чёткими модульными границами
- Модули взаимодействуют через внутренние интерфейсы, а не через сеть
- Сохраняет простость деплоя, но позволяет выделить сервисы при необходимости
- Хороший выбор для средних проектов
Серверless (FaaS):
- Отдельные функции для обработки событий (загрузка завершена → запустить транскодирование)
- Автоматическое масштабирование, оплата за фактическое использование
- Ограничения: cold start, ограничение времени выполнения, vendor lock-in
- Подходит для вспомогательных задач, не для высоконагруженных сервисов
Практическая рекомендация:
Для видеоплатформы с нагрузкой уровня 20 млн DAU микросервисная архитектура — обоснованный выбор. Начинать можно с модульного монолита и постепенно выделять сервисы по мере роста нагрузки и команды. Критичные для производительности компоненты (транскодирование, отдача контента) выделяются первыми.
Вопрос 9. Что представляет собой blob-хранилище, какие примеры существуют и как организовать попадание в популярного контента через CDN?
Таймкод: 00:37:09
Ответ собеседника: Правильный. Blob-хранилище — минималистичное хранилище в форме «загрузить/прочитать», хорошо работает с большими объёмами данных. Пример — S3. Для попадания популярного контента в CDN предлагается сервис аналитики, который собирает счётчики использования и даёт задачу на загрузку в CDN.
Правильный ответ:
Ответ кандидата корректен. Дополним техническими деталями.
Blob-хранилище (Object Storage):
Blob-хранилище — тип хранилища, оптимизированный для хранения неструктурированных данных (binary large objects): видео, изображения, бэкапы, логи. Ключевые характеристики:
- Модель данных: плоское пространство «ключ → объект» (bucket + key), без иерарпии папок (хотя синтаксически ключи могут имитировать путь)
- Операции: PUT (загрузка), GET (чтение), DELETE (удаление), HEAD (метаданные объекта)
- Метаданные: каждый объект сопровождается системными (Content-Type, Content-Length, Last-Modified) и пользовательскими метаданными
- Согласованность: strong read-after-write consistency (для новых объектов) в современных реализациях
- Долговечность: 99.999999999% (11 девяток) за счёт erasure coding и географической репликации
Примеры blob-хранилищ:
- Amazon S3 — стандарт индустрии, S3-совместимый API поддерживается большинством облачных и on-premise решений
- Google Cloud Storage — интеграция с GCP-экосистемой
- Azure Blob Storage — часть Microsoft Azure
- MinIO — open-source S3-совместимое хранилище, развёртывается on-premise
- Ceph RGW — объектный интерфейс распределённого хранилища Ceph
- Backblaze B2 — бюджетная альтернатива S3
Почему не SQL для видеофайлов:
- SQL-базы оптимизированы для структурированных данных и транзакций, а не для хранения файлов размером в гигабайты
- Запись больших blob в БД приводит к фрагментации, росту времени бэкапа, увеличению размера WAL
- Метаданные видео (заголовок, описание, статус) хранятся в SQL/NoSQL, а сам файл — в blob-хранилище; в метаданных сохраняется только ссылка (URL/key)
Организация попадания контента в CDN:
На практике контент попадает в CDN двумя способами:
1. Pull-based (автоматический, наиболее распространённый):
- CDN настроен с Object Storage как origin-сервер
- Когда клиент запрашивает сегмент видео, CDN Edge при промахе кэша автоматически запрашивает его у origin (Object Storage)
- Сегмент кэшируется на edge-сервере с указанным TTL
- Популярный контент естественным образом оказывается в кэше благодаря частым запросам
- Не требует дополнительной инфраструктуры
2. Push-based (предзагрузка)::
- Для ожидаемых событий (премьера сериала, вирусное видео) контент загружается на CDN заранее
- Analytics Service отслеживает метрики: количество просмотров, скорость роста просмотров, география
- При превышении порога — публикует событие в очередь
- CDN Prefetch Worker получает событие и инициирует загрузку сегментов на CDN edge-серверы через API CDN (например, Cache Prefetch API в CloudFront или CDN Purge/Prefetch в Akamai)
- Также можно использовать Origin Shield — промежуточный кэш между edge и origin для снижения нагрузки на Object Storage
Гибридный подход:
- Основной трафик обслуживается pull-based CDN
- Push-based используется для прогнозируемых событий и контента с известным паттерном популярности
- Холодный контент (старые видео с редкими просмотрами) не вытесняет горячий из кэша благодаря LRU/LFU eviction policies CDN
Вопрос 10. Какие проблемы могут возникнуть с метаданными, как спроектировать схему хранения и обеспечить масштабируемость при росте числа записей?
Таймкод: 00:40:23
Ответ собеседника: Правильный. Запись метаданных создаётся единожды и обновляется ограниченное число раз. Счётчики просмотров лучше вынести в отдельную таблицу. Для масштабируемости — master-slave репликация. Объём метаданных ~5 КБ на запись, ~10 МБ в день — SQL-база справится.
Правильный ответ:
Ответ кандидата содержит правильные идеи. Дополним техническими деталями и исправим неточности.
Проблемы с метаданными:
Высокая частота обновлений счётчиков:
- Счётчик просмотров обновляется при каждом просмотре — для популярного видео это тысячи обновлений в секунду
- Прямое обновление строки в основной таблице приводит к contention (блокировкам) и деградации чтения
- Решение: выносить счётчики в отдельную таблицу или использовать счётчики в Redis с периодической фиксацией в БД
Рост объёма данных:
- При 20 000 загрузок/день за год накопится ~7,3 млн записей
- При 5 КБ на запись — ~35 ГБ в год только основные метаданные
- С учётом индексов, счётчиков, истории изменений — объём кратно больше
Сложные запросы:
- Поиск по множеству полей: заголовок, теги, категория, дата, длительность, рейтинг
- Пагинация и сортировка по различным полям
- Персонализированные запросы (подписки, история, рекомендации)
Схема хранения:
Основная таблица метаданных (PostgreSQL/MySQL):
CREATE TABLE videos (
video_id UUID PRIMARY KEY,
user_id BIGINT NOT NULL,
title VARCHAR(500) NOT NULL,
description TEXT,
visibility SMALLINT NOT NULL DEFAULT 0, -- 0=public, 1=unlisted, 2=private
status SMALLINT NOT NULL DEFAULT 0, -- 0=uploading, 1=processing, 2=ready, 3=failed
duration INT, -- секунды
file_size BIGINT,
original_key VARCHAR(500), -- ключ в Object Storage
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
published_at TIMESTAMPTZ
);
CREATE INDEX idx_videos_user_id ON videos(user_id, created_at DESC);
CREATE INDEX idx_videos_status_published ON videos(status, published_at DESC) WHERE status = 2;
Таблица вариантов транскодирования:
CREATE TABLE video_variants (
video_id UUID NOT NULL REFERENCES videos(video_id),
resolution VARCHAR(10) NOT NULL, -- '360p', '720p', '1080p'
codec VARCHAR(10) NOT NULL, -- 'h264', 'av1'
bitrate INT,
file_size BIGINT,
storage_key VARCHAR(500) NOT NULL,
manifest_url VARCHAR(1000),
PRIMARY KEY (video_id, resolution, codec)
);
Таблица счётчиков (отдельно от основной):
CREATE TABLE video_counters (
video_id UUID PRIMARY KEY REFERENCES videos(video_id),
views BIGINT NOT NULL DEFAULT 0,
likes INT NOT NULL DEFAULT 0,
dislikes INT NOT NULL DEFAULT 0,
comments INT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Теги (многие-ко-многим):
CREATE TABLE tags (
tag_id SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL
);
CREATE TABLE video_tags (
video_id UUID NOT NULL REFERENCES videos(video_id),
tag_id INT NOT NULL REFERENCES tags(tag_id),
PRIMARY KEY (video_id, tag_id)
);
Масштабируемость:
Read Replicas:
- Запись идёт в master, чтение распределяется по read replicas
- Для поиска и ленты — чтение с реплик, возможно с eventual consistency
- Для критичных операций (проверка прав доступа) — чтение с master
Шардирование:
- При росте объёма — шардирование по
video_id(hash-based) или поuser_id(для запросов по каналу) - Шардирование по
video_idобеспечивает равномерное распределение - Шардирование по
user_idгруппирует все видео автора на одном шарде, упрощая запросы «все видео канала»
Кэширование:
- Метаданные популярных видео кэшируются в Redis/Memcached
- Cache-aside pattern: при запросе сначала проверяется кэш, при промахе — запрос к БД с последующим заполнением кэша
- TTL зависит от типа данных: статичные метаданные — часы, счётчики — минуты
Вынос поиска в отдельный индекс:
- Полнотекстовый поиск — Elasticsearch/OpenSearch, синхронизация через CDC (Change Data Capture) или event-driven
- Это снимает нагрузку с основной БД и обеспечивает возможности поиска, недоступные в SQL (морфология, релевантность, автодополнение)
Примечание по LSM-деревьям: Кандидат упомянул SQL-базу на LSM-деревьях. Это неточность: LSM (Log-Structured Merge Tree) — это внутренняя структура хранения, используемая в NoSQL-базах (Cassandra, RocksDB, LevelDB). Классические SQL-базы (PostgreSQL, MySQL/InnoDB) используют B+-деревья для индексов. Для метаданных видеоплатформы реляционная БД с B+-деревьями — стандартный и оправданный выбор.
Вопрос 11. Нужен ли балансировщик для сервиса ответов (response service) и как распределить нагрузку между его инстансами, учитывая геораспределённость?
Таймкод: 00:45:36
Ответ собеседника: Правильный. Запросы идут на API Gateway, затем на балансировщик, распределяющий между инстансами. В геораспределённой системе — маршрутизация к ближайшему региону. Пример — Nginx.
Правильный ответ:
Ответ кандидата корректен. Дополним многоуровневой архитектурой балансировки.
Необходимость балансировщика:
Да, балансировщик необходим по нескольким причинам:
- Горизонтальное масштабирование: один инстанс не справится с нагрузкой 20 млн DAU
- Отказоустойчивость: при падении инстанса трафик перенаправляется на здоровые
- Rolling deployments: обновление сервисов без downtime
- Health checking: автоматическое исключение неработающих инстансов из пула
Многоуровневая балансировка:
1. DNS-балансировка (Global Server Load Balancing — GSLB):
- Первый уровень: DNS-резолвер определяет геолокацию пользователя и возвращает IP ближайшего дата-центра
- Пример: Route 53 (AWS) с latency-based или geolocation-based routing
- Пользователь из Европы получает IP европейского кластера, из Азии — азиатского
- TTL DNS-записей — низкий (30-60 секунд) для быстрого failover
2. L4-балансировка (Transport Layer):
- Распределение TCP/UDP-соединений между инстансами или между L7-балансировщиками
- Примеры: AWS NLB, Google Cloud TCP/UDP Load Balancer, HAProxy в TCP-режиме
- Высокая производительность, минимальные накладные расходы
- Алгоритмы: round-robin, least connections, source IP hash
3. L7-балансировка (Application Layer):
- Инспектирует HTTP-запросы: пулы, заголовки, cookies
- Примеры: AWS ALB, Nginx, Envoy, HAProxy в HTTP-режиме
- Возможности: path-based routing (
/api/v1/*→ API service,/static/*→ CDN), sticky sessions, rate limiting, SSL termination
Алгоритмы балансировки:
- Round Robin — равномерное распределение по кругу; подходит при одинаковой мощности инстансов
- Least Connections — запрос направляется на инстанс с наименьшим числом активных соединений; оптимально при разном времени обработки
- Weighted — инстансам назначаются веса пропорционально мощности
- Consistent Hashing — один и тот же ключ (например,
video_id) всегда направляется на один инстанс; полезно для кэширования
Геораспределённая маршрутизация:
- Anycast: один IP-анонсируется из нескольких дата-центров; маршрутизация BGP направляет пользователя к ближайшему
- Geo-based routing: DNS или L7-балансировщик определяет регион пользователя и направляет в соответствующий кластер
- Cross-region failover: при недоступности региона — трафик перенаправляется в ближайший доступный
Пример стека:
Пользователь
│
▼
DNS (Route 53 / Cloudflare) ─── Geo-based resolution
│
▼
CDN (CloudFront / Cloudflare) ─── Кэширование статики и видео
│
▼
API Gateway (Kong / AWS API Gateway) ─── Rate limiting, Auth, Routing
│
▼
L7 Load Balancer (Nginx / Envoy / ALB) ─── Path-based routing
│
▼
Service Mesh (Istio / Linkerd) ─── Межсервисная коммуникация, mTLS, Circuit Breaker
│
▼
Response Service Instances (Kubernetes Pods)
Kubernetes Ingress:
При развёртывании в Kubernetes балансировка инстансов сервиса выполняется на нескольких уровнях:
- Service (ClusterIP): внутренний L4-балансировщик, распределяет Pod'ы сервиса
- Ingress Controller (Nginx/Envoy): L7-балансировка с маршрутизацией по путям и хостам
- Horizontal Pod Autoscaler (HPA): автоматическое масштабирование количества Pod'ов на основе CPU, пользовательских метрик (RPS, длина очереди)
Вопрос 12. Какие языки программирования и технологии выбрать для различных компонентов системы: upload-сервис, брокер сообщений, хранилище метаданных?
Таймкод: 00:50:50
Ответ собеседника: Правильный. Для upload-сервиса — Python с Flask. Для брокера сообщений — Kafka. Для метаданных — PostgreSQL.
Правильный ответ:
Ответ кандидата содержит рабочие варианты, но для системы с нагрузкой 20 млн DAU выбор технологий требует более строгого обоснования.
Upload Service:
Кандидат предложил Python с Flask. Это допустимо для прототипа, но для production с высокой нагрузкой есть более эффективные варианты.
- Go — оптимальный выбор: высокая производительность при обработке сетевых запросов, нативная поддержка concurrency (goroutines), быстрая компиляция, низкое потребление памяти, отличная экосистема для микросервисов (gRPC, Prometheus metrics)
- Java/Kotlin + Spring Boot — зрелая экосистема, отличные библиотеки для работы с БД и брокерами, но более высокое потребление памяти
- Python + FastAPI — быстрая разработка, хорошая производительность для I/O-bound задач (async/await), но GIL ограничивает CPU-bound операции; подходит для сервисов с умеренной нагрузкой
Для upload-сервиса основная нагрузка — I/O-bound (обращения к БД, Object Storage, брокеру), поэтому Python с асинхронным фреймворком приемлем, но Go даст лучшую производительность при меньших ресурсах.
Брокер сообщений:
- Apache Kafka — правильный выбор для основного брокера: высокая пропускная способность, персистентность сообщений, возможность повторного чтения, партиционирование для параллельной обработки, exactly-once semantics
- RabbitMQ — для сценариев с более сложной маршрутизацией сообщений, приоритетными очередями, RPC-паттернами
- Amazon SQS/SNS — managed-решение, проще в эксплуатации, но менее гибкое
Для транскодирования Kafka идеальна: можно создавать отдельные топики для каждого разрешения, масштабировать консьюмеров независимо, гарантировать обработку каждой задачи.
Хранилище метаданных:
- PostgreSQL — правильный выбор: ACID-транзакции, богатые типы данных (JSONB, массивы), полнотекстовый поиск, зрелая экосистема репликации, расширения (PostGIS для геоданных, pg_trgm для fuzzy search)
- MySQL/MariaDB — альтернатива, но менее богатые возможности
- MongoDB — для документ-ориентированных метаданных с гибкой схемой, но отсутствие JOIN и транзакций между коллекциями — ограничение
- Redis — как кэш поверх PostgreSQL, не как основное хранилище
Расширенный стек для других компонентов:
- Transcoding Workers: Go/C++ с FFmpeg, GPU-ускорение (NVIDIA NVENC/NDEC)
- Search Service: Java/Kotlin + Elasticsearch клиент
- API Gateway: Go (Echo/Gin) или Envoy
- Analytics/Metrics: ClickHouse или Apache Druid для аналитики, Prometheus + Grafana для мониторинга
- Object Storage: MinIO (on-premise) или AWS S3
- CDN: CloudFront, Cloudflare, Akamai
- Оркестрация: Kubernetes, Docker
- Service Mesh: Istio или Linkerd для межсервисной коммуникации
Принцип выбора:
Выбор технологии должен определяться не предпочтениями команды, а профилем нагрузки: I/O-bound vs CPU-bound, latency-sensitive vs throughput-oriented, strong consistency vs eventual consistency. Для каждого компонента — свой оптимальный стек.
