SYSTEM DESIGN: WHATSAPP. ЧАСТЬ II
В прошлой части начали проектировать WhatsApp: определили функциональные и технические требования, разобрали модель данных, API и первые два сценария — установку WebSocket-соединения и отправку сообщения.
Продолжаем.
Третья картинка — про статус сообщения. Все очень похоже на отправку сообщения.
⬛Машин клиент получил сообщение и отправил WS Handler подтверждение.
⬛Дальше цепочка по доставке раскручивается в обратную сторону.
Разница: мы не добавляем новую запись в БД, а обновляем существующую.
Такая же схема будет с «прочитано». Клиент по какой-то логике (например, сообщение на экране больше минуты) решает, что можно изменить статус. Отправляет соответствующее сообщение.
Четвертая картинка — про статус человека.
⬛Мишин клиент раз в 5 минут отправляет свой timestamp, когда человек активно пользуется приложением.
⬛WS Handler с этой информацией идет в специальный сервис по работе со статусом человека.
⬛Сервис ведет свою БД с последними обновлениями.
⬛Когда Маше нужен Мишин статус, она спрашивает своего WS Handler об этом.
⬛Он тоже ходит в Last Seen Service и получает оттуда информацию о Мишином статусе.
На этом верхнеуровневая архитектура закончена. Все end-to-end сценарии покрыты. Давайте нырять в детали.
Начнем с выбора БД: для сообщений и статусов скорее всего возьмете NoSQL (обсуждали тут).
Можно поговорить о партиционировании и шардировании (разбирали тему здесь).
Дальше пару слов о том, что в системе напрашивается очередь — есть все 4 признака, которые мы обсуждали здесь. Где вы ее поставили? Например, перед Message Service.
Проговорите возможность масштабирования. Можно пару слов сказать о разнице между горизонтальным и вертикальным. В наших масштабах без горизонтального уже, увы, не обойтись.
Где можно добавить кеш? Например, перед БД статусов. Держать в быстром кеше активных пользователей. Пусть вымывается по TTL.
Подсчеты. Зделаем пару примеров
Операций записи у нас три на каждое сообщение: 1 000 000 000 × 10 × 3 / 86 400 ≈ 347 000 операций записи в секунду.
Столько же чтения, если считать три чтения на каждое сообщение.
Допустим, один сервер WS Handler держит 10 000 RPS. Тогда теоретически нам понадобится около 35 серверов на запись и еще 35 на чтение. Итого 70 (только для сообщений!!!). Но ещё нужен запас, реплики и возможность пережить падение части серверов. Поэтому железа будет больше.
Размер стора. 1 000 000 000 × 10 × 100 бит = 1 000 000 000 000 бит в день, то есть примерно 125 ГБ в день.
Но это только содержимое сообщений. Добавляем ID отправителя и получателя, ID сообщения, timestamp, статус, индексы и прочие служебные данные. Если очень грубо заложить 100 байт на одну запись целиком, получаем: 10 000 000 000 × 100 байт = 1 ТБ в день.
За 5 лет — около 1,8 ПБ. Если делаем три копии данных, получаем около 5,5 ПБ. И это без учета накладных расходов самого хранилища.
Плюсы архитектуры.
⬛Она горизонтально масштабируется: можем добавлять WS Handler'ы и экземпляры сервисов по мере роста нагрузки.
⬛Сообщение сохраняется до попытки доставки, поэтому нам не важно, онлайн получатель или нет.
⬛WebSocket подходит для общения в реальном времени.
⬛Сервисы разделены по ответственности: соединения, сообщения и Last Seen не смешаны в один огромный сервис.
А минусы?
⬛Connection Manager должен постоянно поддерживать актуальный mapping «пользователь → Handler». Соединения рвутся, пользователи переподключаются, Handler'ы падают — придется разруливать все эти случаи.
⬛Нужно аккуратно работать со статусами: например, «прочитано» не должно внезапно превратиться обратно в «доставлено» из-за того, что события пришли не по порядку.
⬛И, конечно, самое гадкое — это размер стора. Нужно точно что-то придумывать.
На System Design от вас не ждут идеальной архитектуры с первой попытки. Важно показать, что вы умеете задавать вопросы, выделять основные сценарии, оценивать нагрузку и видеть узкие места.
Советую вот этот Ютуб канал для подготовки.
#бабанюра_программирует
Post #827
127


- 🔥 3
- 👨💻 1