Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2PC distributed transactions across many microservices?

I read some information about 2 Phase Commit/ XA distributed transactions and how JTA does support it. Seems to be that there is many resource managers - RM (eg. RDBMS or JMS), and one TransactionManager (TM) instance that manages global transactions across many RM's. TM <-> RM communication

I know that it's better to use Saga pattern, but it's still interesting to think:

  1. Do 2PC/XA distributed transactions give the possibility of conducting transactions with many RM's only from one application and one TM?
  2. If no - how to use 2PC/XA distributed transactions between many microservices to provide an ability to use 2PC, if each microservice have access only to own database? I would be glad to see an example
  3. Do we need to use TransactionManager service as a separate microservice to provide 2PC between many microservices?

UPD: In JTA world TransactionManager doesn't provide REST API for managing transactions across microservices. LIXA provides this ability. Article with examples in addition to answers :)

like image 486
Dmitriy Mishenyov Avatar asked Dec 20 '20 17:12

Dmitriy Mishenyov


Video Answer


1 Answers

Across microservices, transaction needs to be done by exposing Prepare & Commit APIs. Also there needs to be a transaction manager to coordinate transaction.

For example, Assume there are 2 different Bank and $100 from Account_A of Bank1 has to be transferred to Account_B of Bank2. Furthermore assume that central banking authority is responsible for transaction to finish the way 2PC will work is like following:

  1. Central banking authority(Transaction Manager) will receive request to transfer $100 from Account_A from Bank1 to Account_B from Bank2.

    a. https://CentralBank/Transaction?from=Bank1-Account_A&to=Bank2-Account_B&amount=100
    
  2. Central Bank will save this into its transaction database with some transaction Id = 123. Also it will return transaction id to call, so that at later point it can call to get status of transaction.

    a. add transaction 123 in database with status open
    
  3. PREPARE PHASE Transaction Manager will issue following RPC commands:

    a. https://Bank1/Prepare?Account=Account_A&money=100&action=subtract&transactionid=123
    b. https://Bank2/Prepare?Account=Account_B&money=100&action=add&transactionid=123
    
  4. COMMIT PHASE Once it gets successful response for both the calls in Prepare phase, then it moves to Commit phase where it issues following commands:

    a. move transaction 123 to committed state
    b. https://Bank1/Commit?transactionid=123
    c. https://Bank2/Commit?transactionid=123
    
  5. Once it gets successful response for both the calls in commit phase, central bank can move transaction to Completed state(optional)

  6. If any of the step from PREPARE or COMMIT phase fails then Transaction coordinator aborts the transaction by issuing following commands:

    a. move transaction 123 to Failed state
    b. https://Bank1/Rollback?transactionid=123
    c. https://Bank2/Rollback?transactionid=123
    

Problem above is form of Distributed Atomic commit, and 2PC is one way of doing it. Also note 2PC has lot of downsides like what if after PREPARE phase central bank crashes. Also what if 4.c step fails but 4.b succeeds, etc. Discussing those is very vast study in itself, but still is something to be aware of. Despite having lot of downsides 2PC is used widely because of its simplicity.


Do we need to use TransactionManager service as a separate microservice to provide 2PC between many microservices?

Theoretically No. If you closely observe any of the bank(Bank1 or Bank2) can act as transaction manager as well(it just needs a separate database table Transaction), but practically lot of time it is kept as separate microservice.

like image 81
WebServer Avatar answered Sep 18 '22 19:09

WebServer