Системный дизайн YouTube

В данной статье мы рассмотрим системный дизайн популярного сервиса YouTube.

Похожие сервисы:

Этапы:

  1. Уточнение требований
  2. Создание API
  3. Оценка требуемых ресурсов
  4. Определение “слабых” мест
  5. Высокоуровневый дизайн (High Level Design – HLD)
  6. Низкоуровневый дизайн (Low Level Design – LLD)

Уточнение требований

Функциональные требования:

  • Загрузка видео: позволить пользователям загружать видеофайлы различных форматов и размеров.
  • Проигрывание видео: обеспечить плавное и качественное воспроизведение видео для всех пользователей.
  • Комментарии: предоставить возможность оставлять комментарии к видео и отвечать на них.
  • Лайки/дизлайки: дать возможность пользователю выразить свое отношение к видео путем оценки лайком или дизлайком.
  • Подписки: позволить пользователям подписываться на каналы и следить за новыми видео.
  • Поиск: предоставить функционал поиска видео по названию, каналам, ключевым словам и т.д.
  • Уведомления: уведомлять пользователей о новых видео, комментариях и других событиях.
  • Статистика и аналитика: собирать и предоставлять статистические данные о просмотрах, подписках, демографии и других метриках для каналов и видео.

Нефункциональные требования:

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

Создание API

Рассмотрим пример API контракта для всех функциональных требований выше.

Загрузка видео

uploadVideo(api_dev_key, video_title, video_description, tags[], category_id, default_language, recording_details, video_contents)

Проигрывание видео

playVideo(api_dev_key, video_id)

Создать комментарий

createComment(api_dev_key, video_id, user_id, comment_text)

Получить комментарии к видео

getVideoComments(api_dev_key, video_id, limit, offset)

Ответить на комментарий

replyToComment(api_dev_key, comment_id, user_id, reply_text)

Оценить видео (лайк/дизлайк)

rateVideo(api_dev_key, video_id, user_id, rating)

Получить количество лайков/дизлайков видео

getVideoRating(api_dev_key, video_id)

Подписаться на канал

subscribeToChannel(api_dev_key, channel_id, user_id)

Отписаться от канала

unsubscribeFromChannel(api_dev_key, channel_id, user_id)

Получить список подписок пользователя

getUserSubscriptions(api_dev_key, user_id, limit, offset)

Поиск видео

searchVideos(api_dev_key, query, filters[], limit, offset)

Поиск каналов

searchChannels(api_dev_key, query, filters[], limit, offset)

Получить список уведомлений пользователя

getUserNotifications(api_dev_key, user_id, limit, offset)

Отметить уведомление как прочитанное

markNotificationAsRead(api_dev_key, notification_id)

Получить статистику видео

getVideoStatistics(api_dev_key, video_id)

Получить статистику канала

getChannelStatistics(api_dev_key, channel_id)

Оценка требуемых ресурсов

Предполагаемые вводные данные:

  • Количество пользователей – 1 000 000 000
  • Количество активных пользователей в день – 500 000 000
  • Количество авторов, которые публикуют видео – 100 000 000
  • Среднее количество публикаций – 2 видео в день
  • Каждый пользователь в среднем просматривает 20 видео в день
  • Максимальный размер видео 256 Гб
  • Средний размер видео – 1 Гб

Хранилище

  • 100 000 000 авторов публикуют по 2 видео в день, что составляет 200 000 000 видео ежедневно.
  • Если максимальный размер видео составляет 256 ГБ, предположим, что средний размер видео составляет 1 ГБ (это зависит от форматов и качества видео).
  • Таким образом, каждый день будет загружаться 200 000 000 ГБ или 200 000 ТБ видео.

Нагрузка (RPS – requests per second)

Загрузка/просмотр видео:

  • Активных пользователей: 500,000,000
  • Предположим, что пользователи просматривают 20 видео в день. Это означает 10,000,000,000 просмотров в день.
  • Также учитываем загрузку видео, которая составляет 200,000,000 в день.
  • Общее количество запросов в день: 10,200,000,000

Лайки/дизлайки:

  • Предположим, что пользователи ставят оценку (лайк или дизлайк) для 5 из 20 просмотренных видео в день.
  • Это составляет 5 * 500,000,000 = 2,500,000,000 лайков/дизлайков в день.

Комментарии:

  • Предположим, что пользователи оставляют комментарии для 2 из 20 просмотренных видео в день.
  • Это составляет 2 * 500,000,000 = 1,000,000,000 комментариев в день.

Подписки и отписки

  • Предположим, что пользователи в среднем подписываются и отписываются от 3 каналов в день.
  • Это составляет 3 * 500,000,000 = 1,500,000,000 подписок/отписок в день.

Резюмируем расчеты:

  • Общее количество запросов (просмотры + загрузки + лайки/дизлайки + комментарии + подписки/отписки) в день: 13,700,000,000 + 1,500,000,000 = 15,200,000,000
  • Чтобы получить RPS, нужно поделить общее количество запросов на количество секунд в день (86400 секунд): RPS = 15,200,000,000 / 86,400 = 175,926

Таким образом, примерная оценка RPS с учетом всех активностей, включая подписки и отписки, составляет около 175926 запросов в секунду.

Повторю, что это лишь примерная оценка, и в реальности RPS может варьироваться в зависимости от паттернов пользовательского поведения и других факторов.

Пропускная способность (Bandwidth)

  • Просмотры: 10,000,000,000 видео в день, средний размер видео 1 ГБ: 10,000,000,000 ГБ данных для передачи.
  • Загрузки: 200,000,000 видео в день, средний размер видео 1 ГБ: 200000000 ГБ данных для передачи.
  • Общий объем данных для передачи в день: 10200000,000 ГБ
  • Чтобы получить пропускную способность в ГБ/сек, нужно поделить общий объем данных на количество секунд в день (86400 секунд): Bandwidth = 10200000000 ГБ / 86,400 сек = 118056 ГБ/сек

Таким образом, примерная оценка пропускной способности составляет около 118056 ГБ/сек или 118,056 * 8 = 944448 Гбит/сек (гигабит в секунду).

Определение “слабых” мест

При проектировании системы, такой как YouTube, потенциальные узкие места (bottlenecks) могут возникнуть из-за множества факторов. Вот некоторые из них:

  1. Пропускная способность и масштабирование:

    Большое количество пользовательских запросов и передача видео между серверами и пользователями может привести к проблемам с пропускной способностью. Оптимизация и масштабирование сетевой инфраструктуры является важным аспектом в решении этой проблемы.
  1. Вычислительная мощность серверов:

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

    Множество запросов на чтение и запись в базу данных могут привести к узким местам. Оптимизация производительности базы данных, использование шардирования и кеширования может снизить нагрузку на базу данных и улучшить производительность системы.
  1. Сеть доставки контента (CDN):

    Без использования CDN, большое количество запросов на видео может перегрузить основные сервера. Использование CDN улучшает производительность, снижает задержки и обеспечивает быстрое воспроизведение видео.
  1. Микросервисная архитектура:

    Если система не разделена на микросервисы, узкие места могут возникнуть из-за монолитной архитектуры. Разделение системы на микросервисы позволяет лучше масштабировать, изолировать проблемы и оптимизировать каждый компонент независимо.
  1. Отказоустойчивость и отказобезопасность:

    Возникновение сбоев в одной части системы может вызвать узкие места или неработоспособность системы в целом. Разработка стратегий резервного копирования, репликации и автоматического переключения на резервные узлы обеспечивает непрерывную работу системы в случае сбоев.
  1. Балансировка нагрузки:

    Неравномерное распределение нагрузки между серверами может привести к перегрузке отдельных узлов и снижению производительности системы. Балансировщики нагрузки помогают равномерно распределять трафик между серверами и обеспечивать эффективное использование ресурсов.
  1. Оптимизация алгоритмов:

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

    Непрерывный мониторинг и анализ производительности системы позволяют оперативно выявлять и устранять узкие места. Использование средств мониторинга, логирования и анализа данных помогает идентифицировать проблемные области и оптимизировать систему.
  1. Безопасность:

    Атаки на систему, такие как DDoS-атаки или попытки взлома, могут стать узким местом и снизить производительность или доступность системы. Обеспечение безопасности системы, использование методов защиты от DDoS-атак и мониторинг нарушений безопасности являются важными элементами проектирования системы.

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

Высокоуровневый дизайн (High Level Design – HLD)

Основными компонентами нашей системы будут следующие компоненты:

  1. Хранилище видео файлов
    Нам понадобится распределенное файловое хранилище для хранения наших медиафайлов.
  2. База данных для информации о пользователях
    Для хранения информации о пользователях, каналах, подписках и т.д.
  3. База данных для метаданных о видео
    Для хранения данных о расположении видео в файловом хранилище, лайках/дизлайках, комментариях и т.д.
  4. Сервер кодировки видео
    Так как мы работаем с огромным количеством данных, имеет смысл приводить входящие медиа файлы к определенному формату и иметь отдельный файлы для разных разрешений (144p, 240p, … 1080p и т.д.) (или форматам). После загрузки видео в файловое хранилище мы можем отправить задачу на кодирование в очередь и сервер кодировки начнет ее обработку.
  5. Сервера приложения
    Серверы приложений нашей микросервисной системы.
  6. Брокер сообщений
    Очередь для передачи асинхронных задач – кодировка, генерация отчетов и т.д.
YouTube System Design (HLD)

Низкоуровневый дизайн (Low Level Design – LLD)

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

Хранилище видео файлов
Для хранения файлов нам понадобится надежное распределенное хранилище файлов. Здесь на ум сразу приходит HDFS (Hadoop distributed file system).

База данных для информации о пользователях

В качестве БД для хранения данных о пользователях мы можем взять MySQL, так как это надежная и простая БД, которая позволит нам применять шардирование либо по геопозиции, либо по идентификатору пользователя. Также нам необходимо предусмотреть механизм проверки видео на уникальность, чтобы не хранить одинаковые видео. Мы могли бы генерировать checksum для каждого видео и хранить ее в БД.

Основные данные о пользователе, которые нам необходимы:

  • Идентификатор
  • email
  • Имя
  • Фамилия
  • Данные об адресе
  • Документы для верификации

База данных для метаданных о видео

В качестве БД для хранения метаданных видео мы также можем MySQL. Для шардирования данных в данном случае лучше использовать идентификатор автора, что позволит хранить все метаданные от одного пользователя на одном сервере. Но геопозиция также подойдет.

Основные данные по видео:

  • идентификатор
  • название
  • описание
  • размер видео
  • автор
  • количество просмотров
  • количество лайков/дизлайков

Комментарии:

  • Идентификатор
  • идентификатор видео
  • родительский комментарий (для ответа)
  • текст комментария
  • вложения в комментарий (при необходимости)

Сервер кодировки видео

После загрузки нового видео на сервер, мы создаем задачу на кодировку видео в нужные форматы и разрешения. Эта задача помещается в очередь обработки, которую прослушивает сервер(а) кодирования. Это позволит нам легко динамически масштабировать сервис горизонтально

Сервера приложения

Мы ожидаем высокую нагрузку на систему и большое количество запросов, поэтому нам необходимо:

  • Разделить траффик на запись и траффик на чтение. Также необходимо предусмотреть механизм обработки ошибок при загрузке видео. Если по какой-то причине загрузка прервалась, необходимо чтобы загрузка продолжалась с точки остановки.
  • Для метаданных по видео мы можем использовать основную БД и несколько реплик для чтения. Как только данные обновляются в основной БД, данные реплицируются и мы сможем распределить нагрузку.
  • Основные данные по видео (количество просмотров, лайки/дизлайки) мы могли бы вынести в хранилище “ключ-значение”, например, Aerospike. Это поможет уменьшить задержки (latency).
  • Нам необходимо внедрить балансировщик нагрузки, чтобы иметь возможность горизонтально масштабироваться.
  • Использование кэша позволит распределить нагрузку и сможем повысить производительность.
  • Внедрение CDN (Content Delivery Network), как системы распределенных серверов для доставки пользователям системы наиболее популярных видео на основании их геопозиции.
  • Внедрение кэша поможет нам снизить

Брокер сообщений

Для доставки задач для кодировки видео нам необходимо использовать брокер сообщений. Так ак нам важно, что бы одна задача была обработана только один раз и доставка была гарантирована – нам стоит использовать очередь. RabbitMQ крайне надежная и зрелая технология, которая доказала свою эффективность.

Резюмируя все сказанное выше, мы можем реализовать финальную диаграмму:

На этом мы завершаем разбор системного дизайна YouTube.