简体   繁体   中英

How to rollback distributed transactions?

I have three different Spring boot Projects with separated databases eg account-rest, payment-rest, gateway-rest.

  1. account-rest : create a new account
  2. payment-rest : create a new payment
  3. gateway-rest : calls other endpoints

at gateway-rest there is an endpoint which calls the other two endpoints.

@GetMapping("/gateway-api")    
@org.springframework.transaction.annotation.Transactional(rollbackFor = RuntimeException.class)
public String getApi()
{
    String accountId = restTemplate.getForObject("http://localhost:8686/account", String.class); 
    restTemplate.getForObject("http://localhost:8585/payment?accid="+accountId, String.class);
    throw new RuntimeException("rollback everything");      
}

I want to rollback transactions and revert everything when I throw exception at gateway or anyother endpoints.

How can I do that ?

It is impossible rollback external dependencies accessible via rest or something like that. The only think that you can do is compensate errors, you can use pattern like SAGA

I hope that is can help you

You are basically doing dual persistence. That's not ideally a good thing because of 2 reasons

  1. It increases the latency and thus have a direct impact on user experience
  2. What if one of them fails?

As the other answer pointed out SAGA pattern is an option to post compensation transaction.

The other option and it's better to go with this by all means is to avoid dual persistence by writing to only one service synchronously and then use Change Data Capture (CDC) to asynchronously upate the other service. If we can design in this way, we can ensure atomicity (all or nothing) and thus probably the rollback scenario itself will not surface.

Refer to these two answers also, if they help: https://stackoverflow.com/a/54676222/1235935 https://stackoverflow.com/a/54527066/1235935

By all means avoid distributed transactions or 2-phase commit. It's not a good solution and creates lot of operational overhead, locking etc. when the transaction co-ordinator fails after prepare phase and before commit phase. Worse things happen when transaction co-ordinator gets its data corrupted.

For that purpose you need external transaction management system. It will handle distributed transations and commit/rollback when its finished on all services.

Possible flow example:

  • Request coming
  • gateway-rest starts a distributed transaction and local transaction and sends a request(with transaction id) to payment-rest. Thread with transaction lives until all local transactions is finished.
  • payment-rest knows about global transaction and starts own local transaction.
  • When all local transactions marked as commited, TM(transaction manager) sends a request to each service to close local transactions and close global transaction.

In your case you can use sagas as mentioned by many others, but they require events and async in nature.

if you want a sync kind of API. you can do something similar to this:

first lets take an example in case of amazon, for creating a order and getting balance out of your wallet and completing the order:

create Order in PendingState
reserveBalance in Account service for order id

if balance reserved change Order state to Confirmed (also having the transaction id for the reserve) and update reserveBalanceConsumed to Account Service

else change Order state to Cancelled with reason , "not enough Balance"

Now there are cases where lets says account service balance is reserved but for some reason order is either not confirmed.

Then somebody could periodically check that if there are reserve Balance for some order and time>30 min let say then check whether that order is marked as confirmed with that trnasaction id , call reserveBalanceConsumed , else cancel that order with reason "some error please try again" , mark balance as free

NOW THESE TYPE OF SYSTEMS ARE COMPLEX TO BUILD. Use the Saga pattern in general for simpler structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM