В данной статье мы рассмотрим системный дизайн популярного сервиса Twitter.
Похожие сервисы:
Этапы:
- Уточнение требований
- Создание API
- Оценка требуемых ресурсов
- Определение “слабых” мест
- Высокоуровневый дизайн (High Level Design – HLD)
- Низкоуровневый дизайн (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:
- Хранение данных:
С увеличением количества пользователей и твитов, хранение большого объема данных становится вызовом. База данных должна быть оптимизирована для быстрого доступа и обработки данных. Разделение данных на шарды может помочь улучшить производительность и масштабируемость системы. - Кэширование:
Чтобы снизить нагрузку на базу данных и ускорить время отклика, кэширование является важным решением. Однако, определение оптимального размера кэша и стратегии истечения срока действия может быть сложным. Неправильная настройка кэширования может привести к проблемам производительности и несоответствию данных. - Таймлайн пользователей:
Вывод твитов в таймлайне пользователей является одной из основных функций Twitter. Оптимизация алгоритма для составления таймлайна таким образом, чтобы он быстро и эффективно отображал актуальные и релевантные твиты, является критическим аспектом системы. Учет пользовательских предпочтений и уведомлений также может добавить сложности. - Поиск твитов:
Поиск твитов – важная функция, которая должна быть оптимизирована для быстрого и точного поиска. Реализация поиска с учетом хештегов, ключевых слов и других фильтров может стать сложным и затруднительным. - Обработка медиафайлов:
Обработка и хранение медиафайлов, таких как изображения и видео, также может стать проблемой. Необходимо оптимизировать хранение, сжатие и передачу медиафайлов, чтобы улучшить производительность и удовлетворить требования пользователей. - Отказоустойчивость и доступность:
Система должна быть способна справляться с отказами и обеспечивать высокую доступность. Реализация горизонтального масштабирования, репликации данных и балансировки нагрузки может помочь в обеспечении надежности системы и ее отказоустойчивости.
- Безопасность:
Безопасность пользовательских данных и защита от злоумышленников являются важными аспектами системы. Необходимо реализовать механизмы аутентификации, авторизации и шифрования, чтобы гарантировать конфиденциальность и безопасность данных. Кроме того, важно уделять внимание проблемам, связанным с DDoS-атаками, XSS и инъекциями SQL. - Обработка больших данных и аналитика:
Система должна быть способна обрабатывать огромное количество данных для анализа и предоставления статистики. Это может стать вызовом для производительности и масштабирования системы. Использование технологий больших данных, таких как Hadoop и Spark, может помочь в обработке и анализе данных. - Сервис-ориентированная архитектура (SOA):
Разделение системы на множество небольших сервисов, каждый из которых отвечает за определенную функцию, может улучшить масштабируемость и производительность. Однако координация и взаимодействие между сервисами могут стать сложными, и важно правильно спроектировать систему для обеспечения гибкости и надежности. - Горизонтальное масштабирование:
Горизонтальное масштабирование позволяет увеличивать количество серверов и ресурсов для обработки большего объема данных и запросов. Однако, правильное проектирование системы и алгоритмов для горизонтального масштабирования может быть сложным и требовать постоянного мониторинга и оптимизации.
Рассмотрев все эти потенциальные узкие места, важно проектировать систему таким образом, чтобы обеспечить оптимальную производительность, масштабируемость и надежность. Это включает в себя использование передовых технологий, таких как NoSQL базы данных, кэширование, очереди сообщений, микросервисы и контейнеры, а также применение лучших практик проектирования и разработки.
Высокоуровневый дизайн (High Level Design – HLD)
Основными компонентами нашей системы будут:
- Клиентская часть (Frontend):
Пользователи взаимодействуют с системой через веб-приложение, мобильное приложение или сторонние клиенты (например, TweetDeck). Эти клиенты обеспечивают пользовательский интерфейс для всех функций, таких как авторизация, создание и чтение твитов, подписки, поиск и уведомления. - API Gateway:
Все запросы от клиентов направляются через API Gateway, который обрабатывает аутентификацию, авторизацию, ограничение скорости и маршрутизацию запросов к соответствующим микросервисам. - Микросервисы:
Система разделена на множество микросервисов, каждый из которых выполняет специфическую функцию, такую как управление твитами, подписками, уведомлениями, поиском и т. д. Микросервисы могут масштабироваться независимо друг от друга для работы с различными нагрузками. - База данных:
Система использует несколько баз данных для хранения различных типов данных. Например, MySQL для хранения твитов, пользователей и их связей, а также полнотекстовый поисковый движок (например, Elasticsearch) для индексации и поиска твитов. - Кэширование:
Для снижения нагрузки на базы данных и улучшения времени отклика используется кэширование. Кэширование может быть реализовано с помощью таких технологий, как Redis или Memcached. - Брокер сообщений
Для асинхронной обработки событий, таких как отправка уведомлений, система использует очереди сообщений (например, Kafka или RabbitMQ). - Балансировщик нагрузки:
Нагрузка на систему распределяется между микросервисами и базами данных с помощью балансировщика нагрузки. - Хранилище медиафайлов:
Медиафайлы, такие как изображения и видео, хранятся на отдельном хранилище, таком как Amazon S3 или Google Cloud Storage. - Аналитика и мониторинг:
Для сбора статистики и анализа данных системы.
Низкоуровневый дизайн (Low Level Design – LLD)
Из всего сказанного выше мы можем сделать вывод, что основной сложностью в системе будет быстрый доступ к твитам (поиск и просмотр). Исходя из этого мы можем детально разобрать каждый из компонентов и выбрать соответствующую технологию.
Микросервисы
- Сервис твитов
- Сервис пользователей
- Сервис уведомлений
Кеширование
Кэширование будет построено на модели 80/20 (20% контента генерирует 80% трафика).
- Кэширование данных: наиболее часто запрашиваемые данные (такие, как твиты, профили пользователей) кэшируются с использованием Redis для уменьшения нагрузки на базу данных и сокращения времени ответа.
- Кэш между клиентом и серверами приложений.
- Кэш между файловым хранилищем и серверами приложений.
- Кэш с истечением срока действия: для оптимального использования ресурсов кэша и обеспечения актуальности данных, мы будем использовать подход LRU (Least Recently Used).
Система мониторинга и аналитики
- Сбор метрик: компоненты системы отправляют метрики производительности, ошибок и другую статистику в систему мониторинга (например, Prometheus, Grafana).
- Алерты и уведомления: на основе собранных метрик система мониторинга генерирует алерты и уведомляет ответственных сотрудников о проблемах и аномалиях в работе системы.
Безопасность и отказоустойчивость
- Аутентификация и авторизация: для доступа к ресурсам системы используется аутентификация на основе токенов (например, JWT) и контроль доступа на основе ролей.
- Резервное копирование данных: регулярно создаются резервные копии данных базы данных и хранилища медиафайлов для восстановления системы в случае сбоев.
- Масштабирование: горизонтальное масштабирование путем добавления новых экземпляров компонентов системы позволяет обеспечить устойчивость к возрастающей нагрузке и снижению производительности.
- Отказоустойчивость: использование техник репликации и шардирования данных, а также деплоймент компонентов системы в разных доступных зонах обеспечивает высокую отказоустойчивость и быстрое восстановление после сбоев.
Структура данных
Для системы Twitter с использованием MySQL, можно создать следующие таблицы для хранения данных:
- 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
- tweets
- id: INT, PRIMARY KEY, AUTO_INCREMENT
- user_id: INT, FOREIGN KEY (REFERENCES users(id))
- content: TEXT
- created_at: TIMESTAMP
- updated_at: TIMESTAMP
- followers
- id: INT, PRIMARY KEY, AUTO_INCREMENT
- user_id: INT, FOREIGN KEY (REFERENCES users(id))
- follower_id: INT, FOREIGN KEY (REFERENCES users(id))
- following
- id: INT, PRIMARY KEY, AUTO_INCREMENT
- user_id: INT, FOREIGN KEY (REFERENCES users(id))
- following_id: INT, FOREIGN KEY (REFERENCES users(id))
- likes
- id: INT, PRIMARY KEY, AUTO_INCREMENT
- user_id: INT, FOREIGN KEY (REFERENCES users(id))
- tweet_id: INT, FOREIGN KEY (REFERENCES tweets(id))
- retweets
- id: INT, PRIMARY KEY, AUTO_INCREMENT
- user_id: INT, FOREIGN KEY (REFERENCES users(id))
- tweet_id: INT, FOREIGN KEY (REFERENCES tweets(id))
- 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.