Spring transaction and message queue, spring transaction queue

Source: Internet
Author: User

Spring transaction and message queue, spring transaction queue

During the development process, a bug occurs because the spring transaction commits the production message later than the message queue, which leads to incorrect data obtained when the message queue consumes the message. This article introduces the problem generation and step-by-step solution process.

I. Problem generation:

Scenario Restoration: A method in the interface, first modifies the order status, and then produces messages to the Message Queue. the consumer of the Message Queue obtains the message detection order status, and finds that the order status has not changed.

Code:

@ Service (orderApi) public class OrderApiImpl implements OrderApi {@ Resource MqService mqService; @ OrderDao orderDao; public void push (String orderId) {// update the order status, the previous status is 1 updateStatus (orderId, 3); // generates the message mqService. produce (orderId);} public viod updateStatus (String orderId, Integer status) {orderDao. updateStatus (orderId, status );}}

Cause: all methods in orderApi have transactions and transaction types.PROPAGATION_REQUIREDTherefore, the data operations of the push method will be submitted after all the push code is executed, before the transaction is committed, the message in the message queue has been generated. Therefore, the order consumed in the message queue may still be 1 in the database. To make the bug more obvious, you can add the following at the end of the push method:

try {Thread.sleep(10000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}

In this way, you will find that the order status is not modified during message consumption.

 

Ii. solution to the problem:

Solution: when updating data, create a transaction to ensure that after the updated code is executed, the transaction for updating the database has been committed. (Make sure that the database operation has been submitted before the message is generated)

According to the above scheme, I first thought of modifying the transaction type of the updateStatus method directly; I changed the transaction type of this method to PROPAGATION_REQUIRES_NEW (create a transaction, if there is a transaction currently, suspends the current transaction ).

However, this is not suitable for two reasons:

1. The transaction type of updateStaus is forcibly modified, which may affect other processes.

2. No transaction is created in the updateStaus method.

The second explanation: spring adds a transaction through the dynamic proxy implemented by BeanNameAutoProxyCreator. It only adds a transaction to the bean object. Currently, calling methods within the class does not trigger the creation of new things.

After the above attempts, I created a new class:

@Service("orderExtApi")public class OrderExtApiImpl {@Resource OrderApi orderApi;public void updateStatusNewPropagation(String orderId) {orderApi.updateStatus(orderId);}}

Add the transaction PROPAGATION_REQUIRES_NEW for the updateStatusNewPropagation method.

This class is only used to create a new transaction for the updateStaus method in orderApi.

OK. The bug has been fixed so far.

But there is still a problem in the Code: operations on the database have been submitted. If an exception occurs in the production message, it is still wrong for the business logic. Therefore, you need to check whether the message generation is complete.

The final orderApi code is as follows:

@ Service (orderApi) public class OrderApiImpl implements OrderApi {@ Resource MqService mqService; @ Resource OrderDao orderDao OrderDao; @ Resource OrderExtApiImpl orderExtApi; public void push (String orderId) {// update order status, the previous status is 1orderExtApi. updateStatusNewPropagation (orderId, 3); // generates a message -- produce checks whether an exception occurs. If 1 is returned, the message is successfully produced. Response response = mqService. produce (orderId); if (response. getCode ()! = 1) {log.info ("Message Queue production message exception:" + response. getErrorMsg () // The production message is abnormal. Reset the status and wait for the next re-execution of orderExtApi. updateStatusNewPropagation (orderId, 1) ;}} public viod updateStatus (String orderId, Integer status) {orderDao. updateStatus (orderId, status );}}

  

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.