Distributed Transactions in Microservice Architecture
While distributed transactions are important to microservices, they are often misunderstood. In this article, we look to iron out these misunderstandings.
Microservices architecture is very popular in recent days to build big systems or applications. However, in this architecture, the most common problem is how to manage distributed transactions across multiple microservices. Here is a brief article on my real-time experience through my project, the actual problem and the possible solutions(patterns) that could solve it.
What is a distributed transaction?
A distributed transaction is a type of transaction with two or more engaged network hosts. Generally, hosts provide resources, and a transaction manager is responsible for developing and handling the transaction.This means that all transactions in the monolithic system are now distributed into multiple services.Here is a customer order example with a monolithic system:
In the above example if a user sends an Order action to a monolithic system, the system will create database trasaction that works over multiple database tables. If any step fails, the transaction can?Roll Back. This is known as ACID (Atomicity, Consistency, Isolation, Durability), which is guaranteed by the database system.
When decomposing above monolithic system into microservice, we created 2 services CustomerMicroservice and OrderMicroservice. Both of these have separate databases.?Here is a customer order example with microservices:
When an Order?request comes from the user, both microservices will be called to apply changes into their own database. Because the transaction is now across multiple databases, it is now considered a?distributed transaction.
What are the Major Problems in Microservices?
To ensure ACID principle (Atomicity, Consistency, Isolation, Durability) in monolithic system, we have database sytem. But in microservice, we need to clarify the following key problems in ACIDity.
Ways to Solve the Major Microservices Problems
The following two patterns can resolve the above problem:
Two-phase commit (2PC) pattern:
2PC is widely used in database systems. For some situations, you can use 2PC for microservices. 2PC has two phases:
In the example above, when a user sends an Order request, the?Middleware or Coordinator?will first create a global transaction (Create Transaction) with all the context information. It will then tell?CustomerMicroservice?to prepare for updating a customer table with the created transaction. The?CustomerMicroservice?will then check, for example, if the customer has enough funds to proceed with the transaction. Once?CustomerMicroservice is OK to perform the change, it will lock down the object from further changes and tell the?Middleware that it is prepared. The same thing happens while creating the order in the?OrderMicroservice. Once the?Middleware has confirmed all microservices are ready to apply their changes, it will then ask them to apply their changes by requesting a commit with the transaction. Once both phases are completed, records will be unlocked.
In the above process, if we get any failure at any point of time, the Middleware will abort the transactions and start the rollback process. Here is a diagram of a 2PC rollback for the customer order example:
领英推荐
In the above sequence diagram, the Customer microservice fails to prepare for some reason, but the Order microservice prepares to create the order. The Middleware will ask to abort all the prepared transactions i.e roll back changes and unlock the records.
Advantages of 2PC
Disadvantages of 2PC
SAGA (3PC) Pattern:
For distributed transactions, The Saga pattern is another widely used pattern.The Saga pattern is asynchronous and more reactive.?It is different from 2PC, which is synchronous.In a Saga pattern, the distributed transaction is fulfilled by asynchronous local transactions on all related microservices. The microservices communicate with each other through an event bus.Here is a diagram of the Saga pattern for the customer order example:
In the example above, the?OrderMicroservice?receives a request to place an order. It first starts a local transaction to create an order and then emits an?OrderCreated?event. The?CustomerMicroservice?listens for this event and updates a customer fund once the event is received. If a deduction is successfully?made from a fund, a?CustomerUpdated?event will then be emitted, which in this example means the end of the transaction.
If any microservice fails to complete its local transaction, the other microservices will run compensation transactions to rollback the changes. Here is a diagram of the Saga pattern for a compensation transaction:
In the above example, the?UpdateCustomer failed for some reason and it then emitted a?CustomerUpdateFailed?event. The?OrderMicroservice?listens for the event and start its compensation transaction to revert the order that was created.
Advantages of the Saga pattern
Disadvantages of the Saga pattern
Conclusion
The Saga pattern is the most preferable way of solving distributed transaction problems for a microservice-based architecture. As a team if we have to adopt the Saga pattern, it requires a change in mindset for both development and testing. Sometimes It could be a challenge for a team that is not familiar with this pattern. Therefore, it is very important to choose the proper way to implement it for a project.
I'm constantly delighted to receive feedback. Whether you spot an error, have a suggestion for improvement, or just want to share your thoughts, please don't hesitate to comment/reach out. I truly value connecting with readers!
Reference
Solution Architect | Architecture and Design | Business Process Modeling and Analysis | Technology Integration | Azure Services | Microservice | Microsoft Dot Net | at Cognizant
1 年The way you explained with an e-commerce application scenario, really great ! Thank you.
Director at UBS
3 年Very well explained.
Director General Digital Transformation and IT Solutions
3 年So?well explained.?Thanks!