https://youtu.be/YPbGW3Fnmbc
  • 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:
  • A compensating action must be idempotent and must have the capability to be retried until it is executed successfully, essentially making it an action that just cannot fail and no manual intervention is required to solve its failure. The Saga Execution Coordinator (SEC) provides that guarantee and capability to the overall flow, making it a transaction that is either successful or aborted successfully with necessary rollbacks.

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

  • Data reliability and Long-lived transactions
  • Request are asynchronous
  • No lock for DB object

Disadvantages of the Saga pattern

  • Difficult to debug/test especially if we have multiple microservices
  • It does not have read isolation i.e user can see the order created but in next second, the order is removed due to failure transaction

How to sequence the saga transactions?

  • After the completion of transaction Ti “something” must
    decide what step to execute next
  • Success: which T(i+1) — branching
  • Failure: C(i-1)
This couples services to the sagas
Services expose APIs that are invoked by saga

SAGA — Choreography

Choreography is a sequence of steps or movements in dance…and it’s also similar in software development if you apply SAGA — Choreography :). With this approach each service produces and listens to other service’s events, based on the event from other services will decide the next action.

Let’s apply SAGA-Choreography to the sample above.

  1. Order service creates a record into the database with status is “Verifying”.
  2. Order service publishes an event “Order is created successfully” and Stock service will listen to this event.
  3. Stock service updates the number of products in the Stock database.

4 & 6. Stock service publishes an event “Product is updated successfully” and Order service and Shipping service will listen to this event.

5. Order service will change the status of the Order to “Shipping”.

7. Shipping service creates a record in the Shipping database.

8. Shipping service publishes an event “Shipping is registered successfully” and Order service will listen to this event.

9. Order Service changes the status of the Order to “Finish”.

Rollbacks flow in SAGA — Orchestration

Rollbacks flow in SAGA — Orchestration

Scenario 1: There is an error with Stock Service.

  1. Order Service create a record in Order DB with status is “Verifying
  2. Order Service publishes an event “Order created successfully” and Stock service will listen to this.
  3. Stock Service update the number of Product in Stock database. But there is an unexpected error when saving Product record.
  4. Stock Service publishes a “rollback” event “Fail to update the number of product in stock”.
  5. Order Service update Order status in Order database to “Failed

Scenario 2: Order service and Stock service run successfully. There is an error with Shipping service.

7. Shipping service creates a record in the Shipping database. But there is an unexpected error when saving.

8 & 9. Shipping service publishes a “rollback” event “Fail to register Shipping service” and both Stock and Order service listen to this event.

10. Order service update Order status in Order database to “Failed

11. Stock service updates the number of the product back to before we change it from Step #3.

Note that it is crucial to define a common shared ID for each transaction, so whenever you throw an event, all listeners can know right away which transaction it refers to.

Advantages and disadvantages of SAGA — Choreography

Choreography is the simplest way to implement SAGA pattern. It’s very easy to understand and doesn’t take too much effort to build up. Each local transaction in chain is independent as they don’t have direct knowledge of each other. If your distributed transaction only includes from 2 to 4 local transactions then Choreography is very fit option.

Having too many local transactions will make tracking which services listen to which events becomes very complex. With the sample above, we only have 3 local transactions but more than 10 steps to handle. Let’s imagine when we have 10 local transactions then what will happen….?

Choreography implementation is preferred when the number of microservices that will participate in the distributed transaction is between 2 and 4. In the case of more than 4 services, it is more appropriate to apply the Orchestration implementation, which we will examine in the rest of our article.

The Saga choreography pattern is ideal when you start your microservices journey (essentially a greenfield development) and understand that it is necessary to introduce process microservices in due course.

SAGA — Orchestration

  • In order to address the complexity of the SAGA pattern, it’s quite normal to add a process manager as an orchestrator.
  • The process manager is responsible for listening to events and triggering endpoints.
  • Back to the sample above, instead of Order service, Stock service and Shipping service have to listen to each other, we will implement a “process manage” and these 3 services will listen to this.

As you can see in the diagram, there is a new “Order Orchestrator” aka process manager. The Order Orchestrator communicates with each service by command/reply style in order to tell them what operation should be performed and when.

  1. Order service creates an Order record into the database with status “Verifying”.
  2. Order service request Order Orchestrator to start the “Order Transaction”.
  3. Order Orchestrator sends an “Update Stock Command” to Stock service.
  4. Stock service updates the number of the ordered product in the database.
  5. Stock service replies to Order Orchestrator with “Stock updated successfully” message.
  6. Order Orchestrator sends an “Update Order Command” to Order Service with information that Stock already updated successfully.
  7. Order Service update Order record in the database with status “Shipping”.
  8. Order Orchestrator sends a “Register Shipping Command” to Shipping service.
  9. Shipping service inserts a new record into the Shipping database.
  10. Shipping service replies to Order Orchestrator with “Shipping registered successfully” message.
  11. Order Orchestrator sends an “Update Order Command” to Order service with information that Shipping already updated successfully.
  12. Order Service updates Order record in the database with status “Finish”.

Rollbacks flow is a lot easier when you have “Order Orchestrator” to coordinate everything.

Rollbacks flow in SAGA — Orchestration

Scenario 1: There is an error with Stock service

5. Stock service replies to Order Orchestrator “Out Of Stock” message.

6. Order Orchestrator sends a “Rollback Order Command” to Order service with information that Stock already updated failed.

7. Order service updates the Order record in the database with status is “Failed”.

Scenario 2: There is an error with Shipping service

10. Shipping service replies to Order Orchestrator “Register shipping is failed” message.

11. Order Orchestrator sends a “Rollback Order Command” to Order service with information that Shipping already registered failed.

12. Order service updates the Order record in the database with status is “Failed”.

13. Order Orchestrator sends a “Rollback Stock Command” to Stock service with information that Shipping already registered failed.

14. Stock service updates the number of the product back to before we change it from Step #4.

Note: In the real project, rollback scenarios will based on the requirement. In my current project, there are 5 scenarios

Through the sample of applying SAGA — Orchestration, we can see that Order Orchestrator knows what is the flow needed to execute a “create order” transaction. If there is an error, it is also responsible for coordinating the rollback by sending the commands to each participant to undo the previous action.

A standard way to model a SAGA — Orchestrator is a State Machine where each transformation corresponds to a command or message. State machines are an excellent pattern to structure a well-defined behaviour as they are easy to implement.

In case you don’t want to build an orchestrator by yourself. You can use Cloud services that can help you, for example :

Advantages and disadvantages of SAGA — Orchestration

SAGA-Orchestration brings to us some advantages:

  • Easy to maintain the whole workflow in one place — Orchestrator.
  • Avoid cyclic dependencies between services. All services only communicate with Orchestrator.
  • The complexity of transaction remains linear when new steps are added.

However, in order to achieve the above advantages, you need to design a smart orchestrator. Besides, having too much logic in the orchestrator might lead to difficulties in maintenance.

Note: Normally, the SAGA pattern usually uses with a message broker (Kafka or RabbitMQ) in order to have better performance, increase reliability and improve scalability.

Implicit vs. explicit orchestrator

Rollback using compensating transactions

  • ACID transactions can simply rollback
  • BUT
  • Developer must write application logic to “rollback” eventually consistent transactions
  • Careful design required!

Sagas complicate API design

  • Request initiates the saga. When to send back the response?
  • Option #1: Send response when saga completes:
    + Response specifies the outcome
    - Reduced availability
  • Option #2: Send response immediately after creating the saga (recommended):
    + Improved availability
    - Response does not specify the outcome. Client must poll or be notified

Revised Create Order API

  • createOrder()
    → return id of newly created order
    → NOT fully validated
  • getOrder(id)
    → Called periodically by client to get outcome of validation

Minimal impact on UI

  • Ul hides asynchronous API from the user
  • Saga will usually appear instantaneous (<= 100ms)
  • If it takes longer →Ul displays “processing” popup
  • Server can push notification to UI

Sagas complicate the business logic

  • Changes are committed by each step of the saga
  • Other transactions see “inconsistent” data, e.g. Order.state = PENDING → more complex logic
  • Interaction between sagas and other operations
    → e.g. what does it mean to cancel a PENDING Order?
    “Interrupt” the Create Order saga
    → Wait for the Create Order saga to complete?

TODO

Don’t understand this — ?

Note: When you can not apply 2PC, RDBMS becomes a “bad choice” in Microservices Architecture, you could only accomplish the same “single entity atomic transaction” but in comparison with “NoSQL”, NoSQL is faster than RDBMS so many times.That is why big enterprises are applying Microservices Architecture, also use NoSQL.

--

--

No responses yet