Three-terminal reliable

  1. The sender and MQ ensure that messages are sent to MQ
  2. Mq guarantees that saved messages are not lost
  3. The consumer and MQ work together to ensure that the message is successfully consumed

The sender and MQ ensure that messages are sent to MQ

If plan a, the rabbitmq is to provide the template with spring boot interface to send you need to call rabbitTemplate. ConvertSendAndReceive () method to send this is when the message to the queue the success will return the result If the failure may be thrown exception But it will lead to longer wait Suitable for high reliable scenario But generally in business development is complete business will send message later Such as insert orders table order to create an order email messages These two steps is to ensure atomicity is successful or failed the rabbitmq support transactions But if the following condition

  • Open the transaction
  • Insert order table
  • Sending MQ Messages
  • Database transaction committed successfully
  • Failed to commit the MQ transaction
  • Message loss

So, if the transaction is to use the rabbitmq message to do it Actually in the extreme case is will be lost Here can use the plan provided by an asynchronous command component at https://github.com/bojiw/asyncmd

  • Open the transaction
  • Insert order table
  • Insert asynchronous command table
  • Commit a database transaction
  • Threads scan asynchronous command tables to retrieve messages
  • Send by rabbitTemplate. ConvertSendAndReceive () method
  • If this fails, retry and report to the police

Scheme 2, if use rabbitTemplate. ConvertAndSend and confirms callback (consumption) and Return (error correction) model

  • ConvertAndSend sending to MQ returns immediately regardless of whether the switch successfully processed it so the concurrency is high
  • Confirm (consume callback) interface ConfirmCallback If messages are successfully sent to rabbitMQ switches, the interface input parameter ACK of true means that the messages are successfully sent to rabbitMQ switches and false means that the messages are abnormal
  • Return(error callback) implementation interface ReturnCallback messages from the switch to the queue are not called back if they fail to be sent to the queue

Above this way if the logic of processing messages failure in the callback when abnormal or application server failed Leads to lose messages Because only a callback This kind of situation can be used to add a message list To insert a message table Then Saul table sends a message confirms the callback The update table If the callback The message table is going to be resent and that’s where the message is going to be resent but generally message consumers are going to be idempotent so that’s not a big problem but if you have the following situation

  • The database has two fields, disk by default 0 and return by default 0
  • Confirm confirms=1. Confirm fails to confirm =2. Error Return =2
  • If the callback is successful, confirm =1 error, the callback fails and the table is not updated successfully return 0
  • If you scan the table, you are not sure if you need to re-send messages, because if the messages are delivered successfully to the queue, return=0
  • Unable to distinguish between send queue success and send queue failure in the case of callback exception

This is where the logic goes wrong so you can only handle the message until it succeeds or not because it usually succeeds except in extreme cases where the queue is deleted by mistake and plan two and Plan one actually send messages at about the same speed in terms of the whole process but plan one is a little bit more reliable

Mq guarantees that saved messages are not lost

Messages, switches, and queues all need to be set up for persistence

The consumer and MQ work together to ensure that the message is successfully consumed

The consumer turns on manual confirmation

acknowledge="manual"
Copy the code

Confirmation of successful rabbitMQ consumption is returned only after the transaction has been successfully processed in the business code

channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
Copy the code

If the service fails to be processed, it is re-queued for consumption

channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
Copy the code

Rabbitmq will continue to try again if it is not sure. If it is dependent on a system that has been down for an hour, it will continue to try again during that hour This will bring certain pressure to the rabbitmq and consumers This also can use asynchronous command component provides scheme of https://github.com/bojiw/asyncmd

  • Receives the message
  • Insert messages into asynchronous commands
  • Rabbitmq success is displayed
  • Asynchronous components perform business logic
  • Failed to invoke the interface and retry
  • You can also set the retry interval as long as 1s for the first three times and an hour for the fourth time