2012-03-02 3 views
7

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

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

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

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

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

ответ

0

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

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

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

Смежные вопросы