Effective Management of Distributed Transactions in Microservices
Written on
In this article, we will delve into the Saga pattern, an asynchronous approach that facilitates a series of transactions across multiple microservices. This pattern involves sending messages or events to initiate the next step in the process. Should any transaction fail, the Saga pattern executes compensating actions to revert the changes made.
As illustrated in the diagram, the Saga pattern consists of a sequence of local transactions within each service. After each service updates its database, it publishes an event or message to trigger the subsequent transaction.
It is essential to implement logic for committing transactions and also to establish a mechanism for reversing actions if an error occurs during the process. All transactions, including compensating ones, are managed through listeners that monitor events or messages from the queue.
The compensating transaction must be idempotent and capable of retrying if the initial attempt fails.
The Saga pattern can be realized through two primary methods:
- Choreography-Based Saga Pattern
- Orchestration-Based Saga Pattern
Choreography-Based Saga Pattern
In the Choreography approach, there is no centralized control, with services listening to a message broker to receive and send messages/events back to the queue for other services to act upon.
The steps involved in the Choreography pattern are as follows:
- The Order Service receives a user request to create an order, initializing it in a PENDING state.
- Following the order creation, it emits an event to the Order Events Channel or Queue.
- The Customer Service listens for this event and attempts to reserve credit.
- The Customer Service then sends an event back to the Order Service.
- The Order Service approves or rejects the order based on the response from the Customer Service.
#### Advantages of the Choreography Pattern
- Simple to implement.
- Suitable for scenarios with a limited number of services involved in transactions.
- Eliminates a single point of failure, as the transaction is distributed among services.
#### Drawbacks of the Choreography Pattern
- Complexity increases with the addition of more services to the transaction.
- For instance, if the Order Service communicates with the Customer Service, which in turn interacts with the Payment Service, the workflow can become convoluted and challenging to debug.
- Potential for deadlocks, where two services might be awaiting each other's events.
Orchestrator-Based Saga Pattern
The Orchestrator-based saga pattern features a centralized component known as the Orchestrator that manages the transaction. This component issues commands to the various services and determines whether to commit or abort based on the outcomes from the participants in the Saga.
If any microservice encounters an issue, the orchestrator triggers the compensating transactions. The Orchestrator can be integrated within the microservice initiating the transaction flow or exist as a separate entity outside of the services.
Orchestrator as a Stand-Alone Component
In this scenario, the Orchestrator operates as an independent service that interacts with the services involved in the transaction. Each service receives commands from the orchestrator and sends event responses back.
Orchestrator as a Component within Order Service
Here, the Create Order Saga acts as the Orchestrator residing within the Order Service.
The steps executed in the Orchestrator pattern are as follows:
- When a user places an order, the Order controller’s endpoint is triggered, calling the Order Service.
- The Order Service instantiates the Create Order Saga Orchestrator, directing the microservices on the local transactions to execute.
- The Saga orchestrator creates the order in a PENDING state.
- It sends a Reserve Credit command to the Customer Service.
- The Customer Service attempts to reserve the credit and reports the outcome back to the Saga orchestrator.
- The Saga orchestrator decides whether to approve or reject the order based on this outcome.
#### Advantages of the Orchestrator Pattern
- The Orchestrator pattern supports complex workflows, accommodating the addition of new services to the transaction.
- It provides better control over the transaction flow and the activities involved.
- Eliminates the risk of cyclic dependencies.
- Saga participants (microservices) remain independent and unaware of other services, promoting separation of business logic.
#### Drawbacks of the Orchestrator Pattern
- Increased design complexity compared to the Choreography pattern due to the need for additional coordination logic.
- The orchestrator represents a single point of failure as it manages the entire workflow.
In this article, we explored the asynchronous transaction management approach in microservices, focusing on the Saga pattern and its two variations: Choreography-based and Orchestrator-based. We examined both patterns in detail, discussing their respective advantages and limitations, allowing for informed choices based on specific use cases.
The Saga pattern enables applications to maintain data consistency across services through local transactions rather than distributed ones. However, implementing this programming model is more complex and time-consuming, as it requires the development of compensating transaction logic across all services.
Overall, asynchronous Saga patterns are generally more efficient for microservices compared to synchronous methods like Two-Phase Commit (2PC) and Three-Phase Commit (3PC). Nonetheless, they come with their own challenges, especially regarding ACID compliance in distributed transactions; thus, it is advisable to avoid distributed transactions whenever feasible.
Thank you for reading, and stay tuned for more insights!