System design — проектируем брокер сообщений

Предисловие

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

О чем статья

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

P.S.: Постараюсь все объяснить обычным языком. Цель помочь тем ребятам которые хотят разобраться. А технической литературы на эту тему много и без меня :)

Общая теория

Брокер сообщений (иначе очереди) - это инструмент который помогает общаться программам в асинхронном режиме. Иначе брокер это курьер который берет письмо у одной программы и отдает её другой.

Пример из жизни

Представьте жизненную ситуацию: вы решили отправить письмо. Написали его и запечатали. На конверте оформили все по шаблону. Посылка готова. К вам приезжает курьер и забирает её. Далее вы продолжаете заниматься своими делами пока курьер разбирается с письмом и доставляет его бабушке в Балашиху или Папе в Рим.

Так получается и с программой: отдает сообщение и продолжает свою работу. Если брокер сказал что письмо оформлено корректно и принято для отправки, то программе больше не нужно "думать" как там дела.

Виды брокеров сообщений

Брокеров можно разделить на два типа:

Умный брокер - этот тот кто получает письмо и как курьер сам связывается с получателем и отдает его.

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

На практике если нужен умный брокер, используют RabbitMQ. А если нужен глупый брокер, то Kafka.

Нужно помнить что все инструменты отличаются и этот случай не исключение

Критерий

RabbitMQ

Apache Kafka

Модель

Сам доставит куда нужно

Сохранит сообщение и будет ждать пока его заберут

Скорость

~10 000 RPS

~1 000 000 RPS

Масштабируемость

Вертикальная

Горизонтальная

Хранение данных

Удаляет сообщение после чтения получателем

Может хранить годами даже прочитанное

Использование

RPC, микросервисы, сделать PHP "Параллельным"

Микросервисы, стириминг, логи

Сложность использования

Проще

Сложнее

Подводим итог этой части

RabbitMQ:
— Кину в нужную очередь, а если адресат не онлайн — оставлю у себя, пока не заберёт.

Kafka:
— Буду кричать в рупор, разошлю всем подряд, и пусть сами разбираются, кому оно нужно.

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

План собеседования

  1. Задаем вопросы

  2. Рисуем драфт схемы

  3. Рассуждаем про инструменты и выбираем что будем использовать

  4. Рисуем финальную схему

  5. Делаем расчеты по железу

Задаем вопросы перед началом работ

Начало работы над любым проектом/задачей или на архитектурном интервью обязательно должен начинаться с разбора границ системы. Иначе можно построить звездолет когда он не требуется или наоборот собрать что-то простенькое и упасть на проде.

  1. Вопрос: существует два вида брокеров умный и глупый какой вариант будем проектировать,
    Ответ: на твой выбор

  2. Вопрос: Есть ли какие-то ограничения по данным? Могут ли передаваться данные большого объема?
    Ответ: давай пока это пропустим. Пока считаем что что-то крупное посылать не будем.

  3. Вопрос: а сколько память будет занимать одно сообщение?
    Ответ: пусть в теле будет передаваться json с небольшим массивом данных. Тело пусть будет не более 1кбайта

  4. Вопрос: подскажите какая нагрузка ожидается?
    Ответ: в сутки очень много запросов.

  5. Вопрос: а подскажите пиковую нагрузку в RPS?
    Ответ: в пике достигает 30К RPS

  6. Вопрос: ожидается ли увеличение системы и нагрузки в обозримом будущем,
    Ответ: да ожидается, на сколько не знаем.

  7. Вопрос: Нужно ли нам сохранять прочитанные сообщения или сразу удаляем?
    Ответ: Давай без сохранения

  8. Вопрос: Какой лимит по времени доставки сообщения?
    Ответ: чем быстрее тем лучше

  9. Вопрос: Насколько система должны быть устойчива к падениям?
    Ответ: хочется надежную технологию 99.99

  10. Вопрос: Как много сервисов будет использовать брокера на запись и чтение?
    Ответ: давай не будем к этому привязываться

  11. Вопрос: учитываем ли мониторинги? И будет ли аллертинг?
    Ответ: мониторинги нужны. Аллертинг дав пропустим.

  12. Вопрос: если при даунтайме будет потеря данных нам это критично?
    Ответ: не хотелось бы, но переживем.

Мы задали вопросы и немного поняли картину которую от нас ждут. Теперь можем приступить к проектированию.

Оставьте в комментариях вопросы и ответы как бы поступали вы находясь на месте интервьюера или собеседующего.

Рисуем базовую схему

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

Базовая схема работы
Базовая схема работы

Внимательные увидят не нужный элемент. Пишите в комментариях что можно убрать из это схемы.

В базовой схеме не пытайтесь нарисовать и учесть все. Лучше накидать базовый драфт и после сказать: Я нарисовал драфт и куда стоит углубиться дальше? Так как задача не крупная, вероятный ответ будет абстрактным

Мне очень нравится, продолжай
Мне очень нравится, продолжай

Это дает нам волю фантазии. И мы можем продолжать рассуждать в слух и реализовать схему.

Важное про выбор инструментов

Здесь сильную роль играет ваш опыт, либо если нет опыта, то хорошая погруженность в технологию. Делать

Redis, я выбираю тебя
Redis, я выбираю тебя

это плохая идея как в работе так и на практике :)

Что должно учитываться при выборе инструмента:

  1. Личные знания.

  2. Понимание что делать если все упало.

  3. Насколько технология популярна. Иначе говоря насколько легко заменить сотрудника для работы с выбранной вами технологией.

  4. Стоимость обслуживания и использования.

Какие БД можем использовать

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

Для данной задачи нам подойдет реляционная БД. Кто-то скажет почему не ZooKeeper? - да можно выбрать его и это хороший выбор. Но напомню у нас тут технопоп, а не технопопа :)

Из реляционных БД самые часто используемые MySQL и PostgreSQL. Тут в принципе на усмотрение каждого, но я выберу MySQL - знаком с ним со времен когда модемы умели говорить:

"КШШШШШШШШШШИИИИИИИИИИИИРРРРРРРРРРРРРРРРРР...ПИИИ-ПИИИ-ПИИИ... ВЖЖЖЖЖЖУУУУУУ... КРРР-КРРР-КРРР..."

Но для справедливости сравним два инструмента

Критерии

MySQL

Zookeeper

Производительность

~50 000 RPS

~ 10 000 RPS

Масштабируемость

Горизонтальная

Вертикальная

Хранение

На жестком диске

Данные в памяти + на жестком диске

Отказоустойчивость

Ниже

Выше для запуска требуется 3 ноды

Сложность

Ниже

Выше

Какой кеш лучше выбрать?

Будем выбирать между Redis и MemCache.

Нам требуется в первую очередь кеширование. Получается из "плюшек" Redis можно выделить только "прогрев из коробки" - это когда при перезагрузке системы, данные в кеш вернуться автоматически. Но мемкеш проще и в вопросах сказано, что нам можно потерять немного данных. Выигрывает мемкеш - дешевле, быстрее ~200K RPS.

Балансировщик нагрузки

Выбираем между NGinx и HAPRoxy.

Критерий

NGinx

HAPRoxy

Производительность

Ниже

Выше

Алгоритмы балансировки

Round-robin, Least Connections

Leastconn, Source-IP, Hash

Чаще используется

Веб сервер, API, статика

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

Сложность

Ниже

Выше

Тут я выберу хапрокси.

Мониторинг

Тут на самом деле выбор за каждым. Я буду рассматривать два варианта: Elasticsearch и Clickhouse. Оба варианта имеют ряд индивидуальных нюансов. В том числе и индивидуальных для разработчика.

Критерий

Elasticsearch

Clickhouse

Скорость записи

Ниже

Выше

Скорость чтения

Высокая

Высокая

Поддержка SQL

Ниже

Полноценно

ОЗУ

Жадная

Экономная

Сильная сторона

Поиск по логам

Агрегация метрик

так как мониторинги очень полезны в реалтайме и может быть полезен поиск по логам я выберу Elasticsearch.

Итоговая схема

Мы выбрали технологии и можем нарисовать итоговую схему

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

Расчет железа

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

Пусть 1 сервер backend с 8ГБ ОЗУ в среднем держит 25000RPS. А 1 сервер backend с 16ГБ ОЗУ в среднем держит 45000RPS.

Получаем что для 30000 RPS нам нужно минимум два сервера 8ГБ, либо один на 16ГБ. Но нужно учитывать что одна машина может выйти из строя в пиковую нагрузку и системе может поплохеть. Я бы выбрал два сервера по 16ГБ чтобы сэкономить на железе и дальше смотрел по нагрузке и по фичам.

Итоговая калькуляция:

  1. Backend 2 сервера с 16ГБ ОЗУ на каждом

  2. Балансировщик: 2 сервера

  3. MC: 2 сервера

  4. Мониторинги: 3 ноды Elasticsearch.

Финал

На архитектурном интервью не ожидайте что вам все расскажут. Именно вы лидируете на нем и именно от вас ожидается инициатива.

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

Обязательно задавайте вопросы на старте, какая бы классная и рабочая не была схема, если вы не расставили рамки на старте, интервью будет считаться не пройденным.

Домашняя работа :)

  1. Оставьте в комментариях вопросы которые вы бы задали на месте соискателя?

  2. А как бы вы отвечали на месте интервьюера?

  3. И как бы вы реализовали схему работы брокера сообщений?

  4. Опишите в виде блок схемы как вы видите работу части backend.