avatarAndre Lucas

Summarize

Microservices — Controlling transactions with SAGA pattern — Choreography

Let’s imagine a scenario where we have a logistic application.

The context is three services:

order-service: In charge of creating orders

trip-service: In charge of managing trips, collecting and delivering orders.

restaurant-service: In charge of managing the restaurant list and its products.

I already wrote about communication between microservices. There are a lot of ways to communicate a service with other. Usually, we can create this communication using message brokers such as RabbitMQ, Apache Kafka, to build an application with loosely coupled, scalability, fault tolerance and responsiveness.

So, the scenario when is created a new order is it:

three microservices communicating between them and with their databases.

after a customer requests a new order, the order—service publishes in a topic and those interested receive the message that a new order has been created.

Problems

  • If happens that the restaurant doesn’t have the product from the new order?
  • If there are any errors at the moment creating the new order?

Transaction in a monolithic service

Before discussing microservices architecture, let’s imagine these services as a module of a monolithic service.

In the monolithic service sure is easier to manage transactions

Food Service — Monolithic Service with a single database
and single transaction in the same service

It happens because in the single service (monolithic) the flow of creating an order happens in the single transaction.

Some frameworks such as Spring provides:

@Transaction
public void execute(){}

Expose provides:

transaction(database) { // Statements here },

both have a programmatic API for beginning, committing and rolling back transactions.

Set of transaction properties — ACID

A transaction is a package of operations and it consists of a set of properties to ensure reliably.

Atomicity — a transaction is a single unit, so if any parts fail (operations) the entire transaction fails.

Consistency — ensure that the database changes state upon a successfully committed transaction.

Isolation — ensure the same state would have been obtained if the transactions were executed sequentially.

Durability — ensure that the transaction will be confirmed

Okay, now we have a brief of how a transaction works and the reason for its existence, we can see the reason that we don’t have mastering of operations when it comes to microservices.

We can see that in the image above, there isn’t consistency, because each microservice has its own database, so we need to use a mechanism to keep the consistency of the data across the databases.

Solution

To resolve those problems that were mentioned before, we have the Saga Pattern.

The Saga Pattern is a sequence of transactions coordinating.

Each transaction updates its database and publishes a message to some message broker to trigger the next transaction.

There are two ways to implement the saga pattern:

  • Choreography
  • Orchestration

Choreography

Step by step — happy path

Happy Path

  1. The order-service receives a POST request to create a new order
  2. The order is created as PENDING
  3. Once the order has been created, an event to order-created-events TOPIC is published
  4. The trip-service and restaurant-service receive the event published by order-service, and creates a trip as PENDING. Also, the restaurant-service checks if the product requested by the order service is available, if so, it runs the business logic to attach the product to the order created and publishes a new event to another TOPIC, order-confirmed-events
  5. The order-service receives the event from order-items-events TOPIC, it is updated with the list of the items and also updated the status as CONFIRMED
  6. Once the order has been its status updated, it publishes an event to the TOPIC order-update-event
  7. The trip-service needs to know that the order was confirmed to change its status from PENDING to CONFIRMED.

Compensable transactions path

Saga uses the compensating transaction to rollback changes.

Step by step — bad path
  1. The order-service receives a POST request to create a new order
  2. The order is created as PENDING
  3. Once the order has been created, an event to order-created-events TOPIC is published
  4. The trip-service and restaurant-service receive the event published by order-service, and it creates a trip as PENDING. Also, the restaurant-service checks if the product requested by the order service is available, in this scenario the product wasn’t available, so, the restaurant-service publishes a cancelled event to the topic order-cancel-event
  5. The order-service receives the event from order-cancel-event TOPIC, and the status is updated as CANCELLED
  6. Once the order has been its status updated, it publishes an event to the TOPIC order-update-event
  7. The trip-service receives the event and changes its status from PENDING to CANCELLED

Pseudo Code

  1. The order-service receives a POST request to create a new order as PENDING
in the order-service

4. The trip-service receives the event published by order-service, and it creates a trip as PENDING.

trip-service

4. The restaurant-service receives the event published by order-service, and it checks if the product requested by the order service is available, if so, it runs the business logic to attach the product to the order created and publishes a new event to the order-confirmed-event TOPIC. If the product is unavailable it publishes an event cancelling the order in the order-cancelled-event TOPIC.

restaurant-service

5. Once the order has been its status updated, it publishes an event to the TOPIC order-update-event

Once the order has been its status updated, it publishes an event to the TOPIC order-update-event

7. And the trip-service gets the update — event always when an order is updated.

Considerations

This pattern enables an application to keep data consistent across multiple services.

The drawback is that we earn more complexity in architecture.

The saga is not just for using with message broker, but using these tools we earn more scalability, fault tolerance, data consistency and other advantages.

For this architecture, you should use a log aggregator, in this post I tell you why.

Full code

References

Read more

Software Development
Software Architecture
Saga Pattern
Development
Microservices
Recommended from ReadMedium