Cenários e soluções de perda de mensagens RocketMQ

Autor: Ji-yun HYY

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

 

Como o MQ é usado no projeto, é inevitável considerar o problema de perda de mensagens. Em alguns cenários que envolvem transações de dinheiro, a perda de mensagens pode ser fatal. Então, quais são os cenários de perda de mensagens no RocketMQ?

Vamos primeiro ao fluxograma de consumo mais simples:

A figura acima contém aproximadamente vários cenários:

  • O produtor gera uma mensagem e a envia para RocketMQ

  • Após o RocketMQ receber a mensagem, ela deve ser salva no disco, caso contrário, os dados serão perdidos após falha de energia ou tempo de inatividade

  • Os consumidores obtêm o consumo de mensagens do RocketMQ. Depois que o consumo é bem-sucedido, todo o processo termina

Esses três cenários podem causar perda de mensagem, conforme mostrado na figura a seguir:

1. Quando o produtor envia uma mensagem para Rocket MQ no cenário 1, se houver um jitter de rede ou comunicação anormal, a mensagem pode ser perdida

2. No Cenário 2, a mensagem precisa ser mantida no disco. Nesse momento, haverá duas situações que farão com que a mensagem seja perdida

  • Para reduzir o IO do disco, o RocketMQ primeiro grava a mensagem no cache do sistema operacional em vez de escrever diretamente no disco.O consumidor obter a mensagem do cache do sistema operacional é semelhante a receber a mensagem diretamente da memória, o que é mais rápido. O tempo será liberado para o disco pelo thread do sistema operacional de forma assíncrona e, em seguida, a persistência da mensagem será realmente concluída. Neste processo, caso a mensagem não tenha completado o flash disk assíncrono, o Broker no RocketMQ ficará inativo, o que fará com que a mensagem seja perdida

  • Se a mensagem foi liberada para o disco, mas os dados não foram copiados, uma vez que o disco foi danificado, a mensagem também será perdida

3. O consumidor obtém a mensagem do RocketMQ com sucesso. Quando a mensagem não é totalmente consumida, o RocketMQ é notificado de que a consumi e, em seguida, o consumidor desativa, mas o RocketMQ acredita que o consumidor consumiu os dados com sucesso, então Os dados ainda estão perdidos.

Então, como garantir perda zero de mensagens?

1. A solução para garantir que as mensagens não sejam perdidas no Cenário 1 é usar o próprio mecanismo de transação do RocketMQ para enviar mensagens. O processo geral é:

  • Primeiro, o produtor envia a meia mensagem para o RocketMQ. Nesse momento, o consumidor não pode consumir a meia mensagem. Se a meia mensagem não for enviada, a lógica de rollback correspondente é executada.

  • Depois que a meia mensagem é enviada com sucesso e o RocketMQ retorna uma resposta bem-sucedida, o link principal do produtor é executado

  • Se o link principal do próprio produtor falhar ao executar, ele reverterá e notificará RocketMQ para excluir a meia mensagem

  • Se o link principal do produtor for executado com sucesso, a meia mensagem de confirmação RocketMQ será notificada para que os consumidores possam consumir esses dados

Entre eles, há alguns RocketMQ que não receberam uma resposta do produtor para operações de confirmação / reversão por um longo tempo. Ligue para os detalhes da interface do produtor. Se você estiver interessado, consulte "Princípio da transação distribuída RocketMQ" (https://blog.csdn.net / LO_YUN / artigo / detalhes / 101673893)

 

Depois que a transação RocketMQ é usada para enviar com sucesso a mensagem do produtor para RocketMQ, pode ser garantido que a mensagem não será perdida neste estágio

2. Para garantir que a mensagem não seja perdida no Cenário 2, primeiro você precisa alterar a estratégia de liberação assíncrona do cache de sistema operacional para uma liberação síncrona. Nesta etapa, você precisa modificar o arquivo de configuração do Broker e alterar o flushDiskType para a estratégia de liberação síncrona SYNC_FLUSH. O padrão é ASYNC_FLUSH limpa o disco de forma assíncrona.

Uma vez que o flash de sincronização retorna com sucesso, então deve ser garantido que a mensagem foi persistida no disco; para garantir que o disco seja danificado sem perder dados, precisamos adotar um mecanismo mestre-escravo para RocketMQ, implantação de cluster e os dados no líder em vários seguidores Todos têm backups para evitar pontos únicos de falha.

3. No cenário 3, quando a mensagem chega ao consumidor, RocketMQ pode garantir que a mensagem não será perdida no código

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

No código acima, RocketMQ registra um ouvinte no consumidor. Quando o consumidor recebe a mensagem, ele chama de volta a função de ouvinte para processar a mensagem dentro.

Quando sua mensagem for processada, ela retornará para ConsumeConcurrentlyStatus.CONSUME_SUCCESS. Somente quando CONSUME_SUCCESS for retornado, o consumidor informará a RocketMQ que terminei de gastar. Nesse momento, se o consumidor estiver fora do ar e a mensagem tiver sido processada, a mensagem não será perdida.

Se o consumidor estiver inativo antes de retornar para CONSUME_SUCCESS, o RocketMQ pensará que seu nó de consumidor está inativo, fará failover automaticamente e entregará a mensagem a outros consumidores no grupo de consumidores para consumir a mensagem e garantir a mensagem Não perdido

Para garantir que a mensagem não se perca, basta escrever a lógica de negócio de consumo da mensagem diretamente no método consumeMessage.Se for necessário fazer alguma operação, como o seguinte 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;
    }
});

Se o thread filho recém-aberto processar as mensagens de forma assíncrona, pode acontecer que a mensagem ainda não tenha sido consumida e o consumidor diga ao RocketMQ que a mensagem foi consumida e, como resultado, a mensagem é perdida devido ao tempo de inatividade.

Usar o conjunto de soluções acima pode garantir perda zero de mensagens ao usar RocketMQ, mas o desempenho e a taxa de transferência também cairão significativamente

  • O uso do mecanismo de transação para transmitir mensagens terá muito mais etapas do que a transmissão de mensagem comum, o que consome desempenho

  • O flashing síncrono é comparado com o flashing assíncrono, um é armazenado no disco e o outro é armazenado na memória, a velocidade não é uma ordem de magnitude

  • Para a organização mestre-escravo, o líder precisa sincronizar os dados para o seguidor

  • Não é possível consumir de forma assíncrona durante o consumo. Você só pode esperar que o consumo seja concluído e, em seguida, notificar RocketMQ que o consumo foi concluído

A perda zero de mensagens é uma faca de dois gumes. Se você quiser usá-la bem, ainda depende do cenário de negócios específico. Escolher a solução certa é o melhor

Acho que você gosta

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