This is the 16th day of my participation in Gwen Challenge.

Star: github.com/Jackson0714… Personal website: www.passjava.cn

Read the directory

  • The background,

  • Two, “Datang has everything” website code

  • Transactions in SQL

  • How do you optimize transaction-free code?

  • How to solve the problem of no transaction?

  • 6. Solutions with compensation functions

The background,

Wukong and Master were on their way to the west for buddhist scriptures. Master bought a blessing bag online. The status of the order shows that the order has been paid, but the status of the electronic blessing bag is not sent.

Goku goes to the back end of the site and finds the developer, Little Black Bear.

The wu is empty: hey, quick check bottom my master’s order, money all gave, lucky bag how haven’t arrive yet? Little black bear: Big Saint, we have also received an abnormal notice. When updating the blessing bag table, the blessing bag record was not updated successfully due to network reasons, so the blessing bag is still not sent. Wukong: the blessing bag has not been sent, then why the order status has been paid? Don’t lie to me, you boy! Big Sage, our database uses MongoDB 3.0, which does not support transactions. The wu is empty: what does the business that you say mean? Little Bear: A transaction is a transaction that holds multiple update or delete or add operations, all of which either succeed or fail. Wukong: That is to say, the first step of the top order status has not been paid to the order has been successfully executed, but the second step of updating the blessing bag failed, did not automatically change the status of the first step of the order back? Little Black bear: Yes, big Saint. The wu is empty: that you how have no refund? Little black bear: Big Sage, we didn’t expect this kind of anomaly to happen. Wukong: let me look at your code.

Two, “Datang has everything” website code

The internal logic of shopping on this website is simplified as follows:

 

Try {order.status = "paid "; // First, update the order status: order paid order.save(); // Save the order luckybag. status = "sent "; // Update the status of the bag: luckybag.save () is sent; // save goodCounts. Count -= 1; // Update inventory goodCounts. Save (); Order.status =" order successful "order.save(); } catch (excption e) {logError(); }Copy the code

So what’s wrong with such code?

If the execution of the first step is successful but the execution of the second step fails and an exception is thrown, then the order status of the first step is still successful, and the fubag status is not updated, which is the problem encountered by master.

So how do you keep the two steps consistent? (Either all or none.)

We all know that transactions exist in SQL, so let’s look at transactions in SQL.

Transactions in SQL

I wrote a previous article on transactions in SQL: 30 minutes full resolution -SQL transactions + Isolation level + blocking + deadlock. Here we use pseudocode to illustrate what the next transaction is.

Take an example of purchasing goods: the user places an order, pays, and then issues a blessing bag, which involves the order table update and luckyBag table update.

Try {update order // update luckyBag // Commit // commit changes to two operations} catch (excption e) {rollback // rollback all operations} end transaction // end transactionCopy the code

If the two operations of updating order status and updating blessing bag status are successful, they will all be submitted to the database for execution. If any problem occurs in any step, they will all be rolled back as if no update operation is performed to ensure data consistency.

How do you optimize transaction-free code?

Since MongoDB 3.0 does not support transactions, it is possible to have inconsistent data (orders paid, bags not sent).

So since we don’t enjoy transaction consistency, how can we optimize this part of the code?

Let’s take a look at the sequence diagram of the code:

According to the sequence diagram above, the step saving is problematic. After the first step is saved successfully, if the second step fails to save, the data is inconsistent. Can we move the save back?

Let’s take a look at the optimized sequence diagram. The overall save will be moved backwards.

The pseudocode is as follows:

Try {order.status = "paid "; // Update order status: order paid luckybag. status = "sent "; Count -= 1; goodCounts -= 1; Order. Status =" Order succeeded "// First step, update order status: order paid luckybag.save (); // Save goodCounts. Save (); Order.save (); } catch (excption e) {logError(); }Copy the code

What are the pros and cons of this approach?

Advantage: If any of the first four steps of business logic processing go wrong, the database records will not be affected

Disadvantages: If there is an error in the last three steps, there is the problem of inconsistent data as in the initial scheme.

So how do you solve this problem?

How to solve the problem of no transaction?

The optimized code may still have inconsistent data, so how can we solve it?

Q.1. If the blessing bag is not automatically sent, can it be reissued now? How to reissue?

Question 2. Can I get a refund? Manual refund or automatic refund? What are the advantages and disadvantages respectively? How do you optimize?

Question 3. What if step 3 fails to update the inventory?

Question 4. How to refund failed, and what to do?

Around the above several problems, we expand to discuss.

Q1.1: How can we make a replacement?

Solution 1: If the second step fails, retry several times immediately (3s for the first time, 8s for the second time, and 20s for the third time). Why are the intervals different? You can leave a comment.

Scheme 2: Put the failed data into the queue (it can be stored in the database or Redis, it is recommended to store it in the database), periodically obtain the abnormal data from the queue and resend it.

Question 1.2: What are the advantages and disadvantages of automatic replacement?

Advantages and disadvantages of Option 1

Advantages:

(1) If the network problem occurs temporarily, you can retry several times in a short period of time to solve the problem.

Disadvantages:

(1) If there is an interface or data problem, retry several times in a short period of time will fail;

(2) In addition, if there are a large number of failures, retry will also consume system resources.

Advantages and disadvantages of Option 2

Advantages:

(1) Put retry into asynchronous task to do, can reduce the occupation of system resources;

(2) If the network fault occurs for a long time, the system will try again after the network is recovered.

Disadvantages:

(1) If abnormal data cannot be resolved by retry, the data in the queue will always be retried and cannot be terminated;

(2) If a large number of data fail due to interface or code problems, a large number of failed data will be accumulated, and retry of a large number of data will also cause a certain pressure on system resources;

(3) Error logs will be recorded if the retry fails. A large number of error logs will interfere with online troubleshooting.

Is there a better way to reissue if it keeps failing? Wouldn’t it make more sense to give users a refund? 例 句 : The customer is in a hurry to return the money. This is actually a compensation measure.

Question 2.1 Can I get a refund?

Of course you can get a refund

Question 2.2 Advantages and disadvantages of automatic refund?

Advantages: Reduce the workload of operation staff

Disadvantages: in some cases, abnormal orders need multiple checks and verification to refund, can not go automatic refund. For example, the logic of the code does not handle some scenarios. A one-size-fits-all refund will result in the money being returned and the goods being sent to the customer.

Question 2.3 How to optimize?

So how do you optimize? Automatic and manual refunds are provided. If manual refunds are required in some abnormal scenarios, the refunds can be manually refunded after verification by the developer.

How to deal with uneven accounts? Find out which accounts are unbalance by way of reconciliation.

Question 3. What should I do if the inventory update fails in the third step?

The easiest scenario to think of is timely retry or queue retry. What’s the problem with that? Queue retry is definitely not feasible for snapkill activities.

Can we do a compensation operation? (Initiate refund, update order status to failed.)

The answer is yes.

Question 4. What should I do if the refund fails

We do compensation for each step that fails, but what do we do if we fail to compensate for one step in the middle? Like you can’t get your money back.

Common schemes:

1. If the refund fails, report to the operation and maintenance personnel or developers

2. Manual refund (disadvantages: manual operation, easy to make mistakes, such as finding the wrong order)

Or 3. Join the queue and automatically refund (disadvantage: Generally refund failure is a code-level problem or wechat side problem, so it is still necessary to check the cause of the problem. During this period, all refund failure will alarm, causing unnecessary interference to the daily monitoring)

In the projects I am working on now, the message of refund failure will be pushed to me in the following two forms:

1. Wechat template message

2. Log alarm SMS service provided by cloud service providers

This is convenient for me to troubleshoot problems, and a quick refund.

6. Solutions with compensation functions

We can design a solution with compensation function:

1. If the first step fails, initiate a refund

2. If the second step fails, update the order status to failed and initiate a refund

3. If the inventory update fails in the third step, the bag will be returned, and the order update status is failed, and a refund will be initiated

4. If step 4 fails to update the order successfully, the inventory will be +1, the bag will be returned, the order status will fail to update, and the refund will be initiated

Welcome to comment and discuss how your system does it?

Welcome to follow my official account: “Wukong Chat Framework”

About the author: 8-year Veteran of Internet workplace | full stack engineer | super dad after 90 | open source practitioner | owner of public number 10,000 fans original number. Blue Bridge signed the author, the author of “JVM performance tuning practice” column, handwritten a set of 70,000 words SpringCloud practice summary and 30,000 words distributed algorithm summary. Welcome to follow my public account “Wukong Chat framework”, free access to learning materials.

I am Wukong, strive to become stronger, become super Saiya people!