Saga pattern
Context and problem
In context of a microservice system, it's very likely that you have applied database per service pattern. Some transactions, however, span multiple services and we need a mechanism to implement such transactions. Since each service owns different database, a local ACID transaction cannot simply be applied.
Conceptual overview
The saga pattern provides transaction management using a sequence of local transactions. Each local transaction updates its own database and publishes a message or event to trigger the next transaction in the saga. If a local transaction fails, the saga must execute compensating transactions that undo changes that were made by preceding local transactions. This example from Microsoft illustrates the pattern
Choreography
Choreography
is a way to coordinate sagas without
a centralized point of control. Each service is aware of the next saga participant after updating its own database. Here's an example of choreography saga
taken from Microsoft
Orchestration
Orchestration
is a way to coordinate sagas with
a centralized point of control. An orchestrator (object) tells the participant what local transactions to execute. Here's an example of orchestration saga
taken from Microsoft
Code details
Saga pattern can be checked in order service. In this example application, orchestration
was chosen to implement the saga pattern. The orchestrator object is a Spring state machine which leverages traditional finite-state machine concepts in computer science. This diagram illustrates states, state transitions and actions of the state machine.
States that are decorated with double circles are start and end states. The arrow illustrate the state transition. There's an action, that will be fired, when the state is changed.
Here is the state machine configuration
And here is the definition for state machine actions
Compensating logic
An example for compensating logic can be found in ValidateOrderFailedAction.java
, where we want to send a message to payment service and revert the payment that user has already checked out