Implementation Strategies for Distributed Saga pattern

Sai Prasanth NG
Sai Prasanth NG
Partner January 03, 2019
#systemarchitecture

Event-driven/Choreographed

In a event-driven architecture, each service listens to events emitted by other services and perform the required action. Let’s take the example of the trip service:

Trip creation flow

When a user requests for a trip creation, Trip service triggers Trip_Created_Event. The Flight service listens to Trip service for the Trip_Created_Event and books a flight and emits Flight_Booked_Event. Car rental service listens to Flight service for the Flight_Booked_Event and books a cab and emits Car_Rented_Event. Hotel reservation service listens to Car rental service for Car_Rented_Event and makes a hotel reservation and emits Room_Reserved_Event. The Trip service listens for the Room_Reserved_Event and updates the Trip state.

In case we failed to book a hotel room we have to execute compensating requests for canceling car booking and canceling the flight ticket.

Compensating requests execution flow

The Car rental service listens for Reservation_Failed event and executes the compensating cancel car booking request and emits Car_Booking_Cancelled event. The flight service listens for Car_Booking_Cancelled event and executes compensating request to cancel flight ticket and emits Flight_Booking_Cancelled event. The trip service listens for this event and updates the state of the trip.

Advantages

  • It is easy to implement
  • Participants are loosely coupled

Disadvantages

  • Can easily become confusing as the application becomes complex.
  • Difficult to trace the flow without observing the live system.
  • Testing will become tricky as all the services should be running.

Command/Orchestration

In this approach, there is a single service which acts as a coordinator for the whole saga. It knows all the steps involved in executing a saga

Requests execution flow

It sends commands to the required services to book a flight, rent a cab and reserve a hotel room.

In case of failure in either of them, it calls the compensating requests for the successful requests. For example, if we fail to reserve a hotel room:

Compensating requests execution flow

It calls the compensating request for the car rental service and flight service.

Advantages

  • The orchestration of the distributed transactions is centralized
  • Reduce participants complexity as they only need to execute/reply to commands
  • Easier to implement
  • Easier to manage a rollback
  • Easy to add new stages to the Saga

Disadvantages

  • We have to manage an extra service
  • We are making smart architecture and dumb services

Points to keep in mind during implementation

We can design our system in such a way that, we send the response to the trip service once the saga execution is complete

  • Advantage: Response specifies the outcome
  • Disadvantage: Reduce availability as the whole saga has to execute before returning a response

We can design our system to return response as soon as the saga execution starts

  • Advantage: Improved availability
  • Disadvantage: Client must poll or be notified to check the status of the Saga execution.

We have to keep in mind on how to cancel a pending operation

  • Whether to wait for it to succeed and then cancel it.
  • Cancel it and make sure if you get the request late, it is not executed.

We can also use asynchronous messaging to ensure saga completes when participants are temporarily unavailable.