Escenarios y soluciones de pérdida de mensajes de RocketMQ

Autor: Ji-yun HYY

Fuente: https://blog.csdn.net/LO_YUN/article/details/103949317

 

Dado que MQ se utiliza en el proyecto, es inevitable considerar el problema de la pérdida de mensajes. En algunos escenarios que involucran transacciones de dinero, la pérdida de mensajes puede ser fatal. Entonces, ¿cuáles son los escenarios de pérdida de mensajes en RocketMQ?

Primero veamos el diagrama de flujo de consumo más simple:

La figura anterior contiene aproximadamente varios escenarios:

  • El productor genera un mensaje y lo envía a RocketMQ

  • Una vez que RocketMQ recibe el mensaje, debe guardarse en el disco; de lo contrario, los datos se perderán después de un corte de energía o un tiempo de inactividad.

  • Los consumidores obtienen el consumo de mensajes de RocketMQ. Una vez que el consumo es exitoso, todo el proceso finaliza

Estos tres escenarios pueden causar la pérdida de mensajes, como se muestra en la siguiente figura:

1. Cuando el productor envía un mensaje a Rocket MQ en el escenario 1, si hay una fluctuación de la red o una comunicación anormal, el mensaje puede perderse.

2. En el escenario 2, el mensaje debe persistir en el disco. En este momento, habrá dos situaciones que harán que el mensaje se pierda

  • Para reducir el IO del disco, RocketMQ primero escribirá el mensaje en la caché del sistema operativo en lugar de escribir directamente en el disco. El consumidor que recibe el mensaje de la caché del sistema operativo es similar a obtener el mensaje directamente de la memoria, que es más rápido. El hilo del sistema operativo vaciará el tiempo en el disco de forma asincrónica, y luego la persistencia del mensaje se completará realmente. En este proceso, si el mensaje no ha completado el disco flash asincrónico, el Broker en RocketMQ estará inactivo, lo que hará que el mensaje se pierda.

  • Si el mensaje se ha vaciado en el disco, pero no se ha realizado una copia de seguridad de los datos, una vez que el disco esté dañado, el mensaje también se perderá.

3. El consumidor obtiene correctamente el mensaje de RocketMQ. Cuando el mensaje no se consume por completo, se notifica a RocketMQ que he consumido el mensaje, y luego el consumidor cae, pero RocketMQ cree que el consumidor ha consumido correctamente los datos, por lo que Los datos aún se pierden.

Entonces, ¿cómo garantizar una pérdida cero de mensajes?

1. La solución para garantizar que los mensajes no se pierdan en el Escenario 1 es utilizar el propio mecanismo de transacción de RocketMQ para enviar mensajes. El proceso general es:

  • Primero, el productor envía el medio mensaje a RocketMQ. En este momento, el consumidor no puede consumir el medio mensaje. Si el medio mensaje no se envía, se ejecuta la lógica de reversión correspondiente.

  • Después de que el medio mensaje se envía correctamente y RocketMQ devuelve una respuesta satisfactoria, se ejecuta el enlace principal del productor.

  • Si el enlace principal del propio productor no se ejecuta, se revertirá y notificará a RocketMQ que elimine el medio mensaje.

  • Si el enlace principal del productor se ejecuta correctamente, se notificará el medio mensaje de confirmación de RocketMQ para que los consumidores puedan consumir estos datos.

Entre ellos, hay algunos RocketMQ que no han recibido una respuesta del productor para operaciones de compromiso / reversión durante mucho tiempo. Vuelva a llamar los detalles de la interfaz del productor. Si está interesado, consulte el "Principio de transacción distribuida de RocketMQ" (https://blog.csdn.net / LO_YUN / article / details / 101673893)

 

Después de que la transacción de RocketMQ se utiliza para enviar con éxito el mensaje del productor a RocketMQ, se puede garantizar que el mensaje no se perderá en esta etapa.

2. Para asegurarse de que el mensaje no se pierda en el Escenario 2, primero debe cambiar la estrategia de descarga asíncrona de la caché del sistema operativo a una descarga síncrona. En este paso, debe modificar el archivo de configuración del agente y cambiar el tipo de disco flushDiskType a la estrategia de descarga síncrona SYNC_FLUSH. El valor predeterminado es ASYNC_FLUSH vacía el disco de forma asincrónica.

Una vez que el flasheo de sincronización regresa exitosamente, entonces se debe asegurar que el mensaje ha sido persistente en el disco; para asegurar que el disco esté dañado sin perder datos, necesitamos adoptar un mecanismo maestro-esclavo para RocketMQ, despliegue de clúster y los datos en el líder en múltiples seguidores. Todos tienen copias de seguridad para evitar puntos únicos de falla.

3. En el escenario 3, cuando el mensaje llega al consumidor, RocketMQ puede garantizar que el mensaje no se pierda en el código.

//注册消息监听器处理消息
consumer.registerMessageListener(new MessageListenerConcurrently() {
   @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context){                                  
        //对消息进行处理
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

En el código anterior, RocketMQ registra un oyente en el consumidor. Cuando el consumidor recibe el mensaje, volverá a llamar a la función de oyente para procesar el mensaje en su interior.

Cuando su mensaje sea procesado, volverá a ConsumeConcurrentlyStatus.CONSUME_SUCCESS. Solo cuando se devuelva CONSUME_SUCCESS, el consumidor le dirá a RocketMQ que he terminado de consumir. Si el consumidor está inactivo, el mensaje se ha procesado y el mensaje no se perderá.

Si el consumidor está inactivo antes de regresar a CONSUME_SUCCESS, RocketMQ pensará que su nodo consumidor está inactivo y automáticamente hará una conmutación por error y entregará el mensaje a otros consumidores en el grupo de consumidores para consumir el mensaje y garantizar el mensaje. No perdido

Para asegurar que el mensaje no se pierda, basta con escribir la lógica empresarial del consumo de mensajes directamente en el método consumeMessage. Si tiene que hacer alguna operación, como el siguiente código

//注册消息监听器处理消息
consumer.registerMessageListener(new MessageListenerConcurrently() {
   @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context){ 
     //开启子线程异步处理消息
     new Thread() {
   public void run() {
    //对消息进行处理
   }
  }.start();                                 
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

Si el hilo secundario recién abierto procesa los mensajes de forma asincrónica, puede suceder que el mensaje aún no se haya consumido y el consumidor le diga a RocketMQ que el mensaje se ha consumido y, como resultado, el mensaje se pierde debido al tiempo de inactividad.

El uso del conjunto de soluciones anterior puede garantizar una pérdida de mensajes cero cuando se usa RocketMQ, pero el rendimiento y el rendimiento también se reducirán significativamente.

  • El uso del mecanismo de transacción para transmitir mensajes tendrá muchos más pasos que la transmisión de mensajes ordinaria, que consume rendimiento

  • El destello sincrónico se compara con el destello asíncrono, uno se almacena en el disco y el otro se almacena en la memoria, la velocidad no es un orden de magnitud en absoluto

  • Para la organización maestro-esclavo, el líder necesita sincronizar los datos con el seguidor.

  • No es posible consumir de forma asíncrona durante el consumo. Solo se puede esperar a que se complete el consumo y luego notificar a RocketMQ que el consumo se ha completado

La pérdida cero de mensajes es un arma de doble filo. Si desea utilizarlo bien, aún depende del escenario empresarial específico. Elegir la solución adecuada es la mejor

Supongo que te gusta

Origin blog.csdn.net/csdn_lulinwei/article/details/108596549
Recomendado
Clasificación