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

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

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

Этапы:

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

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

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

  • Регистрация и аутентификация пользователей
  • Создание твитов (текст, изображения, видео)
  • Чтение твитов (лента, профиль)
  • Лайки и ретвиты
  • Подписки и отписки
  • Поиск (по хештегам, пользователям, ключевым словам)
  • Уведомления (например, о новых подписчиках, упоминаниях)
  • Профили пользователей (аватар, описание, статистика подписок и твитов)

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

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

Создание API

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

Регистрация

registerUser(username, password, email)

Аутентификация

loginUser(username, password)

Создание твита

createTweet(access_token, content, media_ids)

Чтение твита

getTweet(access_token, tweet_id)

Изменение твита

updateTweet(access_token, tweet_id, content, media_ids)

Удаление твита

deleteTweet(access_token, tweet_id)

Лайк твита

likeTweet(access_token, tweet_id)

Дизлайк твита

unlikeTweet(access_token, tweet_id)

Ретвит

retweetTweet(access_token, tweet_id)

Подписаться на автора

followUser(access_token, user_id)

Отписаться от автора

unfollowUser(access_token, user_id)

Чтение твитов

getTimeline(access_token)

Получение уведомлений

getNotifications(access_token)

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

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

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

Хранилище

Допустим, что пользователи Twitter хранят твиты в течение 5 лет. Общее количество твитов за 5 лет:

300,000,000 твитов/день * 365 дней * 5 лет = 547,500,000,000 твитов

Объем хранилища:

547,500,000,000 твитов * 1 КБ = 547,500,000,000 КБ = ~547.5 ПБ (петабайт)

Итого: ~547.5 ПБ

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

Публикация твитов:

100,000,000 пользователей * 3 твита/день = 300,000,000 твитов/день 

RPS для публикации твитов:

(300,000,000 твитов/день) / (24 * 60 * 60) = ~3,472 RPS

Чтение твитов: ~347,222 RPS

Лайки:

500,000,000 * 10 лайков/день = 5,000,000,000 лайков/день RPS для лайков: (5,000,000,000 лайков/день) / (24 * 60 * 60) = ~57,870 RPS

Подписки:

500,000,000 * 2 подписки/день = 1,000,000,000 подписок/день RPS для подписок: (1,000,000,000 подписок/день) / (24 * 60 * 60) = ~11,574 RPS

Отписки:

500,000,000 * 1 отписка/день = 500,000,000 отписок/день RPS для отписок: (500,000,000 отписок/день) / (24 * 60 * 60) = ~5,787 RPS

Поиск твитов: 500,000,000 * 5 поисков/день = 2,500,000,000 поисков/день RPS для поиска твитов: (2,500,000,000 поисков/день) / (24 * 60 * 60) = ~28,935 RPS

Общий RPS:

350,694 (публикация и чтение твитов) + 57,870 (лайки) + 11,574 (подписки) + 5,787 (отписки) + 28,935 (поиск твитов) = ~454,860 RPS

Итого: ~454,860 RPS

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

Общий трафик на публикацию твитов: 300,000,000 твитов/день * 1 КБ = 300,000,000 КБ/день

  • Bandwidth для публикации твитов: (300,000,000 КБ/день) / (24 * 60 * 60) = ~3,472,000 КБ/s = ~3.472 Гбит/s
  • Bandwidth для чтения твитов: ~347 Гбит/сек
  • Лайки: 5,000,000,000 лайков/день * 0.5 КБ = 2,500,000,000 КБ/день
  • Подписки: 1,000,000,000 подписок/день * 0.5 КБ = 500,000,000 КБ/день
  • Отписки: 500,000,000 отписок/день * 0.5 КБ = 250,000,000 КБ/день
  • Поиск твитов: 2,500,000,000 поисков/день * 0.5 КБ = 1,250,000,000 КБ/день

Общий трафик: 2,500,000,000 (лайки) + 500,000,000 (подписки) + 250,000,000 (отписки) + 1,250,000,000 (поиск твитов) = 4,500,000,000 КБ/день

Bandwidth для дополнительных операций: (4,500,000,000 КБ/день) / (24 * 60 * 60) = ~52,083 КБ/сек = ~52.083 Мбит/s

Общий Bandwidth:

350.472 Гбит/ек (публикация и чтение твитов) + 0.052 Гбит/сек (лайки, подписки, отписки, поиск твитов) = ~350.524 Гбит/сек

Итого: ~350.524 Гбит/сек

Резюмируя необходимые ресурсы:

  • RPS: ~454,860
  • Bandwidth: ~350.524 Гбит/сек
  • Хранилище ~547.5 ПБ

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

В системе Twitter, потенциальные узкие места (bottlenecks) могут возникнуть из-за высокой нагрузки на систему и масштабирования. Определим и распишем несколько основных bottlenecks:

  1. Хранение данных:

    С увеличением количества пользователей и твитов, хранение большого объема данных становится вызовом. База данных должна быть оптимизирована для быстрого доступа и обработки данных. Разделение данных на шарды может помочь улучшить производительность и масштабируемость системы.
  2. Кэширование:

    Чтобы снизить нагрузку на базу данных и ускорить время отклика, кэширование является важным решением. Однако, определение оптимального размера кэша и стратегии истечения срока действия может быть сложным. Неправильная настройка кэширования может привести к проблемам производительности и несоответствию данных.
  3. Таймлайн пользователей:

    Вывод твитов в таймлайне пользователей является одной из основных функций Twitter. Оптимизация алгоритма для составления таймлайна таким образом, чтобы он быстро и эффективно отображал актуальные и релевантные твиты, является критическим аспектом системы. Учет пользовательских предпочтений и уведомлений также может добавить сложности.
  4. Поиск твитов:

    Поиск твитов – важная функция, которая должна быть оптимизирована для быстрого и точного поиска. Реализация поиска с учетом хештегов, ключевых слов и других фильтров может стать сложным и затруднительным.
  5. Обработка медиафайлов:

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

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

    Безопасность пользовательских данных и защита от злоумышленников являются важными аспектами системы. Необходимо реализовать механизмы аутентификации, авторизации и шифрования, чтобы гарантировать конфиденциальность и безопасность данных. Кроме того, важно уделять внимание проблемам, связанным с DDoS-атаками, XSS и инъекциями SQL.
  2. Обработка больших данных и аналитика:

    Система должна быть способна обрабатывать огромное количество данных для анализа и предоставления статистики. Это может стать вызовом для производительности и масштабирования системы. Использование технологий больших данных, таких как Hadoop и Spark, может помочь в обработке и анализе данных.
  3. Сервис-ориентированная архитектура (SOA):

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

    Горизонтальное масштабирование позволяет увеличивать количество серверов и ресурсов для обработки большего объема данных и запросов. Однако, правильное проектирование системы и алгоритмов для горизонтального масштабирования может быть сложным и требовать постоянного мониторинга и оптимизации.

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

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

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

  1. Клиентская часть (Frontend):
    Пользователи взаимодействуют с системой через веб-приложение, мобильное приложение или сторонние клиенты (например, TweetDeck). Эти клиенты обеспечивают пользовательский интерфейс для всех функций, таких как авторизация, создание и чтение твитов, подписки, поиск и уведомления.
  2. API Gateway:
    Все запросы от клиентов направляются через API Gateway, который обрабатывает аутентификацию, авторизацию, ограничение скорости и маршрутизацию запросов к соответствующим микросервисам.
  3. Микросервисы:
    Система разделена на множество микросервисов, каждый из которых выполняет специфическую функцию, такую как управление твитами, подписками, уведомлениями, поиском и т. д. Микросервисы могут масштабироваться независимо друг от друга для работы с различными нагрузками.
  4. База данных:
    Система использует несколько баз данных для хранения различных типов данных. Например, MySQL для хранения твитов, пользователей и их связей, а также полнотекстовый поисковый движок (например, Elasticsearch) для индексации и поиска твитов.
  5. Кэширование:
    Для снижения нагрузки на базы данных и улучшения времени отклика используется кэширование. Кэширование может быть реализовано с помощью таких технологий, как Redis или Memcached.
  6. Брокер сообщений
    Для асинхронной обработки событий, таких как отправка уведомлений, система использует очереди сообщений (например, Kafka или RabbitMQ).
  7. Балансировщик нагрузки:
    Нагрузка на систему распределяется между микросервисами и базами данных с помощью балансировщика нагрузки.
  8. Хранилище медиафайлов:
    Медиафайлы, такие как изображения и видео, хранятся на отдельном хранилище, таком как Amazon S3 или Google Cloud Storage.
  9. Аналитика и мониторинг:
    Для сбора статистики и анализа данных системы.
Twitter System Design (HLD)

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

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

Микросервисы

  • Сервис твитов
  • Сервис пользователей
  • Сервис уведомлений

Кеширование

Кэширование будет построено на модели 80/20 (20% контента генерирует 80% трафика).

  • Кэширование данных: наиболее часто запрашиваемые данные (такие, как твиты, профили пользователей) кэшируются с использованием Redis для уменьшения нагрузки на базу данных и сокращения времени ответа.
  • Кэш между клиентом и серверами приложений.
  • Кэш между файловым хранилищем и серверами приложений.
  • Кэш с истечением срока действия: для оптимального использования ресурсов кэша и обеспечения актуальности данных, мы будем использовать подход LRU (Least Recently Used).

Система мониторинга и аналитики

  • Сбор метрик: компоненты системы отправляют метрики производительности, ошибок и другую статистику в систему мониторинга (например, Prometheus, Grafana).
  • Алерты и уведомления: на основе собранных метрик система мониторинга генерирует алерты и уведомляет ответственных сотрудников о проблемах и аномалиях в работе системы.

Безопасность и отказоустойчивость

  • Аутентификация и авторизация: для доступа к ресурсам системы используется аутентификация на основе токенов (например, JWT) и контроль доступа на основе ролей.
  • Резервное копирование данных: регулярно создаются резервные копии данных базы данных и хранилища медиафайлов для восстановления системы в случае сбоев.
  • Масштабирование: горизонтальное масштабирование путем добавления новых экземпляров компонентов системы позволяет обеспечить устойчивость к возрастающей нагрузке и снижению производительности.
  • Отказоустойчивость: использование техник репликации и шардирования данных, а также деплоймент компонентов системы в разных доступных зонах обеспечивает высокую отказоустойчивость и быстрое восстановление после сбоев.

Структура данных

Для системы Twitter с использованием MySQL, можно создать следующие таблицы для хранения данных:

  1. users
    • id: INT, PRIMARY KEY, AUTO_INCREMENT
    • username: VARCHAR, UNIQUE
    • email: VARCHAR, UNIQUE
    • password_hash: VARCHAR
    • full_name: VARCHAR
    • bio: TEXT (опционально)
    • profile_image: VARCHAR (опционально)
    • created_at: TIMESTAMP
    • updated_at: TIMESTAMP
  2. tweets
    • id: INT, PRIMARY KEY, AUTO_INCREMENT
    • user_id: INT, FOREIGN KEY (REFERENCES users(id))
    • content: TEXT
    • created_at: TIMESTAMP
    • updated_at: TIMESTAMP
  3. followers
    • id: INT, PRIMARY KEY, AUTO_INCREMENT
    • user_id: INT, FOREIGN KEY (REFERENCES users(id))
    • follower_id: INT, FOREIGN KEY (REFERENCES users(id))
  4. following
    • id: INT, PRIMARY KEY, AUTO_INCREMENT
    • user_id: INT, FOREIGN KEY (REFERENCES users(id))
    • following_id: INT, FOREIGN KEY (REFERENCES users(id))
  5. likes
    • id: INT, PRIMARY KEY, AUTO_INCREMENT
    • user_id: INT, FOREIGN KEY (REFERENCES users(id))
    • tweet_id: INT, FOREIGN KEY (REFERENCES tweets(id))
  6. retweets
    • id: INT, PRIMARY KEY, AUTO_INCREMENT
    • user_id: INT, FOREIGN KEY (REFERENCES users(id))
    • tweet_id: INT, FOREIGN KEY (REFERENCES tweets(id))
  7. comments
    • id: INT, PRIMARY KEY, AUTO_INCREMENT
    • user_id: INT, FOREIGN KEY (REFERENCES users(id))
    • tweet_id: INT, FOREIGN KEY (REFERENCES tweets(id))
    • content: TEXT
    • created_at: TIMESTAMP
    • updated_at: TIMESTAMP

Эти таблицы представляют основные сущности системы Twitter, такие, как пользователи, твиты, подписки, лайки, ретвиты и комментарии. В зависимости от требований, структура таблиц может быть дополнена дополнительными полями и индексами для оптимизации производительности и функциональности системы.

Twitter System Design (LLD)

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