То, что я собираюсь описать, по существу является проблемой двухфазной фиксации между двумя разрозненными системами, и я ищу совет относительно того, как с этим справиться. В нашем веб-приложении мы выгружаем некоторые дорогостоящие/сторонние операции, такие как отправка писем, на внеполосные фоновые рабочие процессы (мы называем это нашей рабочей инфраструктурой.)Two Phase Commit - Как эффективно использовать мою очередь?
Чтобы отправить электронное письмо, например, мы создаем в нашей базе как объект электронной почты, так и адрес электронной почты. Затем нам нужно подождать, пока наш монитор работы запишет работу по электронной почте и отправит ее. Монитор работы в основном работает, опросив базу данных каждые несколько секунд, когда он простаивает.
Это, однако, добавляет задержку в отправку электронной почты и добавляет то, что я рассматриваю как чрезмерную нагрузку на базу данных с помощью опроса. Было бы гораздо приятнее, если бы мы сразу могли отправить задание электронной почты в очередь, как только будет создано электронное письмо.
Однако в настоящее время это не удается по двум причинам. Во-первых, очередь часто намного быстрее, чем веб-запрос. Письмо подбирается для обработки до того, как веб-запрос совершил транзакцию с базой данных, поэтому он не может правильно генерировать электронную почту. Во-вторых, если веб-запрос выходит из строя, он откатывает транзакцию своей базы данных, что означает, что электронное письмо должно быть отправлено не. Однако, если он уже был помещен в очередь, то он больше не находится в контроле запроса.
Есть ли хорошая стратегия для создания двухфазного фиксации между очередью и базой данных? Для справки, мы используем RabbitMQ и MySQL с таблицами InnoDB. Одна из моих идей заключалась в том, чтобы хранить задания электронной почты в очереди после того, как транзакция базы данных была зафиксирована, но это оставляет возможность того, что письмо никогда не будет поставлено в очередь. Мне все равно придется создать процесс опроса, который следит за сообщениями электронной почты, которые должны были быть отправлены, и не были.