Ответ вслух Senior Разборы систем спрашивают часто обновлено

Спроектируйте мессенджер

Вопрос

Спроектируйте мессенджер с личными и групповыми чатами, доставкой в реальном времени и историей.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Требования: личные и групповые чаты, доставка в реальном времени, офлайн через push, история, статусы доставки, порядок внутри чата. Нагрузка: 50 млн DAU по 40 сообщений это 2 млрд в сутки, около 20 000 сообщений в секунду, в пике втрое больше.

Что должно прозвучать в ответе

  • Требования: личные и групповые чаты до 1 000 участников, доставка онлайн и офлайн (push), история, статусы «доставлено» и «прочитано»; порядок сообщений в чате; медиа и сквозное шифрование вне рамок

  • Оценка нагрузки: 50 млн DAU по 40 сообщений ≈ 2 млрд в сутки ≈ 20 000 RPS записи, в пике ~60 000; 10 млн одновременных соединений, ~100 000 на gateway → ~100 gateway; 2 млрд × 200 байт ≈ 400 ГБ в сутки, ~150 ТБ в год без реплик

  • API: WebSocket: send {chat_id, client_msg_id, text}, ack {msg_id}, события new_message, read; HTTP: GET /chats/{id}/messages?before=...

  • Данные: чаты и участники в PostgreSQL, сообщения в Cassandra/ScyllaDB с ключом партиции chat_id и сортировкой по msg_id, реестр user_id → gateway в Redis с TTL

  • Компоненты: gateway-серверы с соединениями, сервис сообщений (сохранить, присвоить id, разослать), сервис присутствия, push-сервис для офлайн, очередь для фан-аута в группах

  • Узкие места: большие группы (фан-аут через очередь), дубли при переотправке (client_msg_id для идемпотентности), переподключения и догрузка пропущенного, горячие чаты, падение gateway

Что могут спросить следом

  • Как гарантировать порядок сообщений в чате?
  • Что происходит, если получатель офлайн?
  • Как не потерять сообщение при обрыве связи у отправителя?

Разбор

Требования: личные и групповые чаты, доставка в реальном времени, офлайн через push, история, статусы доставки, порядок внутри чата. Нагрузка: 50 млн DAU по 40 сообщений это 2 млрд в сутки, около 20 000 сообщений в секунду, в пике втрое больше. Онлайн одновременно около 10 млн, при 100 000 соединений на gateway нужно около 100 серверов. Объём около 400 ГБ в сутки. Клиент держит WebSocket с gateway. Отправка: клиент шлёт сообщение с client_msg_id, сервис сообщений сохраняет его в Cassandra с партицией chat_id, присваивает id, монотонный внутри чата, и отвечает ack, повтор с тем же client_msg_id не создаёт дубль. Затем по участникам чата смотрит в Redis, на каких gateway они сидят, и отправляет туда; офлайн-участникам уходит push. Клиент после переподключения догружает историю по последнему известному id. Большие группы раскладываю через очередь. Узкие места: падение gateway (клиенты переподключаются к другому, реестр обновляется по heartbeat), горячие чаты, рост хранилища, который решается шардированием по chat_id и холодным хранением старой истории.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.