Two Phase Commit - Как эффективно использовать мою очередь? - PullRequest
7 голосов
/ 02 марта 2012

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

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

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

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

Есть ли хорошая стратегия для создания двухфазного коммита между очередью и базой данных? Для справки мы используем RabbitMQ и MySQL с таблицами InnoDB. Одна идея, которую я возглавил, заключалась в том, чтобы помещать задания электронной почты в очередь после совершения транзакции с базой данных, но при этом остается вероятность того, что электронное письмо никогда не попадет в очередь. Мне все еще придется создать процесс опроса, который отслеживает электронные письма, которые должны были быть отправлены, а не отправлены.

1 Ответ

0 голосов
/ 15 февраля 2014

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

Вы можете отправить сообщение с задержкой, чтобы увеличить вероятность того, что БД готовакогда работа получит это.Я никогда не использовал RabbitMQ, но нашел этот пример использования очереди rabbitMQ в качестве отложенной очереди Как создать отложенную очередь в RabbitMQ? .Ваша работа с электронной почтой все равно должна иметь дело с любыми незакомментированными записями, так как задержка не является детерминированным методом работы с распределенной обработкой.

Тем не менее, кажется, что есть место для улучшения вашего дизайна.Как правило, для сервисных архитектур плохая идея делить таблицы БД между сервисами.Это приводит к проблемам распределенных транзакций и масштабирования.Я хотел бы убедиться, что сообщение RabbitMQ содержит все данные, необходимые для обработки электронной почты независимо от какой-либо другой службы.Или, если ему нужно больше данных, он должен запросить эти данные через запрос ServiceBus вместо запроса БД.

...