«Я хочу попасть на большую фабрику» Смертельный сериал MQ 11 вопросов

Java
«Я хочу попасть на большую фабрику» Смертельный сериал MQ 11 вопросов

После предыдущей серии смертей mysql я обнаружил, что мой титул часто использовался, какой опасный для жизни смотритель зоопарка, много опасной для жизни многопоточности, на этот раз я начал серию вопросов для интервью, тему MQ, очередь сообщений как обычно центр ежедневного использования Интервью также является одним из моментов, которые необходимо задать.Давайте посмотрим на вопросы интервью MQ.

почему вы используете mq? Каковы конкретные сценарии использования?

Роль mq очень проста: срезать вершины и заполнять долины. В сценарии размещения заказа в транзакции электронной коммерции процесс форвардной транзакции может включать создание заказа, вычет запасов, вычет бюджета деятельности, вычет баллов и т. д. Если потребление времени каждого интерфейса 100 мс, то по идее вся ссылка заказа будет занимать 400 мс, что явно слишком долго.

Если все эти операции обрабатываются синхронно, то, во-первых, ссылка вызова слишком длинная, чтобы повлиять на производительность интерфейса, а во-вторых, трудно справиться с проблемой распределенных транзакций. не требуют таких высоких требований согласованности в реальном времени, полностью могут обрабатываться асинхронно через mq. В то же время, учитывая несогласованность, вызванную асинхронностью, мы можем использовать job для повторной попытки, чтобы гарантировать успех вызова интерфейса, и, как правило, у компаний будет платформа для проверки.Например, проблема успешного размещения заказа, но без начисления баллов. можно проверить как итоговое решение.

image-20200926174106778

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

Какой MQ вы используете? Что сделано выбор?

В основном мы исследовали несколько основных mq, kafka, rabbitmq, RocketMQ, ActiveMQ, Мы в основном учитываем следующие моменты для выбора:

  1. Поскольку нагрузка на количество запросов в секунду в нашей системе относительно высока, основное внимание уделяется производительности.
  2. Язык разработки, поскольку наш язык разработки — java, в основном предназначен для удобства вторичной разработки.
  3. Это необходимо для бизнес-сценариев с высокой степенью параллелизма, поэтому необходимо поддерживать проектирование распределенной архитектуры.
  4. Функционал обширный.В связи с различными бизнес-сценариями могут использоваться последовательные сообщения, сообщения о транзакциях и т. д.

Исходя из вышеупомянутых соображений, мы наконец выбрали RocketMQ.

Kafka RocketMQ RabbitMQ ActiveMQ
Автономная пропускная способность 100 000 100 000 10000 класс 10000 класс
Язык разработки Scala Java Erlang Java
Высокая доступность Распределенная архитектура Распределенная архитектура архитектура «ведущий-ведомый» архитектура «ведущий-ведомый»
представление мс уровень мс уровень нам класс мс уровень
Функции Поддерживаются только основные функции MQ Полные функции, такие как последовательные сообщения и сообщения о транзакциях Сильный параллелизм, хорошая производительность, низкая задержка Зрелые продукты сообщества, богатая документация

Вы упомянули асинхронную отправку выше, как можно гарантировать надежность сообщения?

Потеря сообщений может возникнуть в трех аспектах: производитель отправляет сообщение, MQ сам теряет сообщение, а потребитель теряет сообщение.

продюсер потерял

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

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

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

  1. После размещения заказа сначала сохраните локальные данные и таблицу сообщений MQ. В это время статус сообщения отправляется. Если локальная транзакция завершается сбоем, заказ завершается сбоем, и транзакция откатывается.
  2. Если заказ выполнен успешно, он напрямую вернет успех клиента и асинхронно отправит сообщение MQ.
  3. Результат отправки уведомления об обратном вызове MQ, соответствующий статусу отправки базы данных MQ
  4. Опрос JOB превышает определенное время (время в соответствии с бизнес-конфигурацией) и не отправил успешное сообщение для повторной попытки.
  5. В конфигурации платформы мониторинга или в программе JOB обрабатываются сообщения, которые были безуспешно отправлены более определенного количества раз, тревоги и ручное вмешательство.
image-20200928221524715

Вообще говоря, форма асинхронного обратного вызова достаточна для большинства сценариев, и только для сценариев, где необходимо полностью гарантировать, что сообщения не будут потеряны, мы сделаем полное решение.

MQ потерян

Если производитель гарантирует, что сообщение отправляется в MQ, и MQ все еще находится в памяти после получения сообщения, в это время он находится вниз, и нет времени синхронизировать на ведомый узел, что может привести к потере сообщения Отказ

Например RocketMQ:

RocketMQ делится на два способа: синхронный сброс и асинхронный сброс. По умолчанию используется асинхронный сброс, который может привести к потере сообщений до того, как они будут сброшены на жесткий диск. Вы можете установить метод синхронного сброса, чтобы обеспечить надежность сообщений. , так что даже если MQ зависнет, сообщение можно будет восстановить с диска при его восстановлении.

Например, Kafka также может сделать это через конфигурацию:

acks=all 只有参与复制的所有节点全部收到消息,才返回生产者成功。这样的话除非所有的节点都挂了,消息才会丢失。
replication.factor=N,设置大于1的数,这会要求每个partion至少有2个副本
min.insync.replicas=N,设置大于1的数,这会要求leader至少感知到一个follower还保持着连接
retries=N,设置一个非常大的值,让生产者发送失败一直重试

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

потребитель потерял

Сценарий, в котором потребитель теряет сообщение: потребитель только что получил сообщение, а сервер в это время не работает MQ считает, что потребитель уже использовал сообщение и не будет отправлять сообщение повторно, и сообщение будет потерял.

RocketMQ по умолчанию требует ответа на подтверждение подтверждения потребителя, но kafka необходимо вручную отключить автоматическое смещение конфигурации.

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

image-20200928221622132

Вы говорили о проблеме сбоя потребительского потребления, так что же делать с бэклогом сообщений, если потребление постоянно сбоит?

Потому что, рассматривая проблему, заключающуюся в том, что потребители ошибались в потреблении, мы можем рассматривать ее со следующих точек зрения:

  1. Ошибки потребителя должны быть вызваны программами или другими проблемами.Если это легко исправить, сначала устраните проблему, а потребитель возобновит нормальное потребление.
  2. Если слишком поздно для обработки, это очень хлопотно, выполните обработку пересылки, напишите временный план потребления потребителя, сначала обработайте сообщение, а затем перенаправьте его в новую тему и ресурсы MQ, применяются машинные ресурсы этой новой темы. отдельно, и должен быть в состоянии нести Текущее отставание сообщений
  3. После обработки невыполненных данных восстановите потребителя для использования нового MQ и существующих данных MQ и восстановите исходное состояние после завершения нового потребления MQ.
image-20200928221718499

Затем, если количество невыполненных сообщений достигает верхнего предела диска, что мне делать, если сообщение удалено?

Этот. . . Черт возьми, что я могу сделать? . . Успокойтесь и подумайте еще раз. . Там есть.

img

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

Сказав так много, можете ли вы рассказать о принципе реализации RocketMQ?

RocketMQ состоит из кластера реестра NameServer, кластера производителя-производителя, кластера-потребителя-потребителя и нескольких брокеров (процессов RocketMQ).Его архитектурный принцип выглядит следующим образом:

  1. Брокер регистрируется на всех серверах имен при запуске, поддерживает длительное соединение и отправляет пульс каждые 30 секунд.
  2. Producer получает адрес сервера Broker от Name Server при отправке сообщения, выбирает сервер согласно алгоритму балансировки нагрузки для отправки сообщения
  3. Когда Conusmer потребляет сообщения, он также получает адрес брокера от NameServer, а затем активно извлекает сообщения для использования.
image-20200928220108061

Почему RocketMQ не использует Zookeeper в качестве реестра?

Я думаю, что следующие причины являются причинами не использовать zookeeper:

  1. Согласно теории CAP одновременно могут быть удовлетворены не более двух пунктов, и zookeeper удовлетворяет CP, а значит, zookeeper не может гарантировать доступность услуг. весь кластер находится в состоянии «Недоступен», что определенно неприемлемо для реестра, так как обнаружение служб должно быть рассчитано на доступность.
  2. Исходя из соображений производительности, сама реализация NameServer очень легковесна, и ее можно масштабировать горизонтально, добавляя машины для повышения устойчивости кластера к давлению, при этом написание zookeeper не масштабируется, и zookeeper может решить эту проблему только путем деления поле , разделить несколько кластеров zookeeper для решения, во-первых, это слишком сложно для работы, а во-вторых, это нарушает дизайн A в CAP, что приводит к отключению между службами.
  3. Проблема, вызванная механизмом постоянства, заключается в том, что протокол ZAB ZooKeeper будет продолжать записывать журнал транзакций на каждом узле ZooKeeper для каждого запроса на запись, и в то же время он будет периодически зеркалировать данные памяти (Snapshot) на диск, чтобы гарантировать непротиворечивость и постоянство, но для простого сценария обнаружения сервисов это на самом деле не нужно, такая реализация слишком тяжелая. И данные, хранящиеся сами по себе, должны быть сильно настроены.
  4. Отправка сообщений должна быть слабо зависима от реестра, и концепция дизайна Rocketmq основана на этом. Производитель получает адрес брокера от имен при отправке сообщения в первый раз, а затем кэширует его локально. Если весь кластер имен , короткий период времени возникнет. Он не оказывает большого влияния на производителей и потребителей.

Брокер - как сохранить данные, которые это?

Основные файлы хранилища RocketMQ включают файлы журнала фиксации, файлы очереди потребления и файлы индексных файлов.

После того, как брокер получит сообщение, он сохранит сообщение в файл журнала коммитов, и в то же время в распределенном хранилище каждый брокер сохранит часть данных топика, и в то же время будет сгенерирован файл потребления очереди под очередь сообщений, соответствующая каждой теме.Чтобы сохранить смещение смещения физической позиции журнала фиксации, соответствующая связь между ключом и смещением будет сохранена в файле индекса.

image-20200929095434327

Файл CommitLog сохраняется в каталоге ${Rocket_Home}/store/commitlog. На рисунке видно смещение имени файла. Каждый файл по умолчанию имеет значение 1G, и новый файл создается автоматически, когда он заполняется.

image-20200929095534558

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

image-20200929100257054

Как синхронизировать данные между Master и Slave?

Синхронизация сообщений между мастером и слейвом осуществляется по протоколу raft:

  1. После того, как брокер получит сообщение, оно будет помечено как незафиксированное.
  2. Затем сообщение будет отправлено всем ведомым устройствам.
  3. Подчиненное устройство возвращает мастеру ответ подтверждения после получения сообщения.
  4. Мастер помечает сообщение как зафиксированное после получения более половины подтверждений.
  5. Отправьте зафиксированное сообщение всем ведомым устройствам, и ведомые устройства также изменят статус на зафиксированное.

Вы знаете, почему RocketMQ такой быстрый?

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

  1. Когда мы пишем в ContimeLog, мы пишем последовательно, что значительно улучшит производительность случайного письма.
  2. При записи в журнал фиксации он не записывается непосредственно на диск, а сначала записывается в PageCache операционной системы.
  3. Наконец, операционная система асинхронно сбрасывает данные из кеша на диск.

Что такое транзакционные, полутранзакционные сообщения? Как?

Сообщения о транзакциях — это XA-подобные возможности распределенных транзакций, предоставляемые MQ, и окончательная согласованность распределенных транзакций может быть достигнута с помощью сообщений о транзакциях.

Полутранзакционное сообщение — это сообщение, которое MQ получил от производителя, но не получил вторичного подтверждения и не может быть доставлен.

Принцип реализации следующий:

  1. Производитель сначала отправляет полутранзакционное сообщение в MQ.
  2. MQ возвращает подтверждение подтверждения после получения сообщения
  3. Производитель начинает выполнять локальную транзакцию
  4. Если транзакция выполнена успешно, фиксация отправляется в MQ, а в случае сбоя отправляется откат.
  5. Если MQ долгое время не получал второго подтверждения фиксации или отката от производителя, MQ инициирует обратную проверку сообщения производителю.
  6. Производитель запрашивает конечное состояние выполнения транзакции
  7. Отправить второе подтверждение снова в соответствии с статусом транзакции запросов

Наконец, если MQ получает второй коммит с подтверждением, он может доставить сообщение потребителю, и наоборот, если это откат, сообщение будет сохранено и удалено через 3 дня.

image-20200929103720817