Take a refund function as an example, how to ensure that refunds, database updates, and sending text messages are all done or not done?

if it"s just a bunch of database operations, it can also be solved with transactions.
if the operations involved are multi-layered, how do you ensure their consistency?
if you do it one by one in order, if you fail to do the previous one, you will not do the latter, and the harm will be less. But it is best to undo what has been done before, which is difficult and almost impossible (when the refund is submitted, it is impossible to recover the refund; when the data is updated, the old data is lost and cannot be restored to the original data; Br > what is more serious is that if a refund is successfully submitted to the payment method, but the local database fails to update, and the "refund" is not recorded, it will inevitably lead to a bad debt.
so how on earth should this kind of problem be dealt with?
Please take my example as a refund question to answer.

Oct.21,2021

put the controllable last and the least anxious last.

there are too many situations in different scenarios.
in the refund process, we can control sending text messages and updating the database. We can send SMS no matter what, and even if it fails, it will only slightly affect the user experience, so we can do it at the end, after we make sure that the payment channel is refunded and the database is updated. Just send it at will.

the refunds / payments of Wechat and Alipay are in callback mode, and the client will be notified to modify the database only after the channel is completed, which is actually protecting the consistency of the data, because the refund may fail, and the channel also has to interact with the bank interface, such as a refund to a bank card but the card status is abnormal? Account status abnormal? All of them may cause refund failure, so we can't take it for granted that the refund will be successful, so we can only modify the database when we receive a callback.

from this point of view, there is only one thing we need to ensure (the channel will push it repeatedly until the success, and the network problem can be ignored), that is, after initiating a refund, ensure that the data can be updated correctly, and before receiving a callback (failure / success), prohibit users from modifying data to avoid data conflicts.

for example, although the withdrawal operation has not been completed (callback has been received), the amount should also be frozen from the available balance and deducted from the balance after receiving the callback. This is the status of Alipay's cash withdrawal on the way
.

We have to consider the situation of failure. What happens if the refund fails?

it doesn't really matter, because the order status in our database is in process or in effect. After a refund failure, you can choose to retry automatically or remind the user that you can do it step by step.


all transactions need to be rollback. As in your example, it is impossible to roll back if you send a text message. Has the message been sent successfully? has the other party received the message successfully? None of this is deterministic, so it is not feasible to add this to transaction consistency.

for rollback, as long as it is finally consistent, it is up to you to decide what to do according to your needs, such as using MQ or text logging. Use your example:

submit refund-> update data.

in terms of business logic, it would be better to "update the data and then submit a refund", because the updated data can be rolled back, but the refund is generally non-rollback.

in practice, you can simply update the data with the help of database transactions, and then go to the refund, get the refund results, and then commit the database.

complex can be done by two-phase commit and so on.

finally, as a reminder, to really achieve automatic final consistency requires extremely high availability. In general, note that there are occasional problems with log, and reconcile through scripted transactions.


record the log, query the reason for the database update failure, write code according to the log, modify the data and call the SMS interface to solve the problem of database record failure. There will be BUG. All you have to do is stop the loss. In general, financial transactions have data streams and transaction logs for maintenance and stop losses.

Menu