two three transactions queue 2phase-commit

transactions - three - Compromiso de dos fases: ¿cómo utilizar mi cola de forma efectiva?



two phase commit (1)

Lo que voy a describir es esencialmente un problema de confirmación en dos fases entre dos sistemas dispares y estoy buscando consejos sobre cómo manejarlo. En nuestra aplicación web, descargamos algunas operaciones caras / de terceros, como el envío de correos electrónicos, a procesos fuera de banda de trabajadores en segundo plano (lo llamamos nuestra infraestructura de trabajo).

Para enviar un correo electrónico, por ejemplo, creamos un objeto de correo electrónico y un trabajo de correo electrónico en nuestra base de datos. Luego tenemos que esperar a que nuestro supervisor de trabajo recoja el trabajo de correo electrónico y lo envíe. El supervisor de trabajos funciona básicamente al sondear la base de datos cada pocos segundos cuando está inactiva.

Esto, sin embargo, agrega una demora en el envío de correo electrónico y agrega lo que veo como una carga indebida en la base de datos con el sondeo. Sería mucho mejor si pudiéramos poner inmediatamente el trabajo de correo electrónico en la cola tan pronto como se cree el correo electrónico.

Sin embargo, esto actualmente falla por dos razones. En primer lugar, la cola suele ser mucho más rápida que la solicitud web. El correo electrónico se recoge para su procesamiento antes de que la solicitud web haya cometido su transacción de base de datos, por lo que no puede generar correctamente el correo electrónico. En segundo lugar, si la solicitud web falla, revierte la transacción de la base de datos, lo que significa que no se debe enviar el correo electrónico. Sin embargo, si ya se ha puesto en la cola, ya no está en control de la solicitud.

¿Existe una buena estrategia para crear una confirmación en dos fases entre la cola y la base de datos? Como referencia, estamos usando RabbitMQ y MySQL con tablas InnoDB. Una idea que encabecé fue incluir los trabajos de correo electrónico en la cola después de que se haya confirmado la transacción de la base de datos, pero eso deja la posibilidad de que el correo electrónico nunca se ponga en cola. Todavía tendré que crear un proceso de votación que busque correos electrónicos que deberían haberse enviado y que no.


Me doy cuenta de que esto es un par de años tarde :) pero quería agregar algunas reflexiones sobre esto para otros que se topan con esta pregunta.

Puede enviar el mensaje con retraso para aumentar las posibilidades de que la base de datos esté lista cuando los trabajos lo reciban. Nunca he usado RabbitMQ, pero encontré este ejemplo de usar una cola rabbitMQ como cola retrasada ¿Cómo crear una cola retrasada en RabbitMQ? . Su trabajo de correo electrónico aún tendría que tratar con los registros sin comentar, ya que el retraso no es un método determinista para tratar el procesamiento distribuido.

Dicho esto, parece que hay espacio para mejorar tu diseño. En general, con las arquitecturas de servicios es una mala idea compartir tablas db entre servicios. Conduce a transacciones distribuidas y problemas de escala. Intentaría asegurarme de que el mensaje RabbitMQ contenga todos los datos que necesita para procesar el correo electrónico independientemente de cualquier otro servicio. O si necesita más datos, debe solicitar esos datos a través de una solicitud ServiceBus en lugar de una consulta DB.