Using Saga
Using Saga
Using Saga
Founder of eventuate.io
Author of Microservices Patterns
Founder of the original CloudFoundry.com
Author of POJOs in Action
@crichardson
chris@chrisrichardson.net
http://eventuate.io http://learn.microservices.io
@crichardson
Presentation goal
@crichardson
About Chris
@crichardson
About Chris
@crichardson
About Chris
@crichardson
For more information
40%
discount
with code
ctwsaturn18
http://learn.microservices.io
@crichardson
Agenda
Overview of sagas
Coordinating sagas
@crichardson
The microservice architecture
structures
an application as a
set of loosely coupled
services
Microservices enable
continuous delivery/deployment
Process:
Continuous delivery/deployment
Services
=
testability
Enables
Enables
and
Successful
Software deployability
Development
Organization: Architecture:
Small, agile, autonomous, Microservice architecture
cross functional teams Enables
Review Review
Team Service
Order Order
Team Service
… …
Team Service
@crichardson
Microservice architecture
Database per service
HTML
Store Customer Customer
Browser
Front UI Service Database
REST
Mobile
Device … …
Service Database
@crichardson
Private database
!=
private database server
@crichardson
Loose coupling =
encapsulated data
Order Service Customer Service
Customer
Order table
table
orderTotal creditLimit
availableCredit
Pre-conditions:
• customerId is valid
Post-conditions
• Order was created
• Customer.availableCredit -= orderTotal
Customer class
Spans Invariant:
services
availableCredit >= 0
availableCredit <= creditLimit
@crichardson
Cannot use ACID transactions
that span services
Distributed transactions
BUT
2PC coordinator is a single point of failure
Chatty: at least O(4n) messages, with retries O(n^2)
….
@crichardson
Basically
ACID Available
Soft state
Eventually consistent
http://queue.acm.org/detail.cfm?id=1394128 @crichardson
Agenda
Overview of sagas
Coordinating sagas
@crichardson
From a 1987 paper
@crichardson
Use Sagas instead of 2PC
X
Distributed transaction
Saga
Service A Service B Service C
Local Local Local
transaction transaction transaction
@crichardson
Create Order Saga
createOrder() Initiates saga
Order Order
Customer
state=PENDING state=APPROVED
@crichardson
But what about rollback?
BEGIN TRANSACTION
…
UPDATE …
…
INSERT ….
…
…. BUSINESS RULE VIOLATED!!!! Really simple!
…
ROLLBACK TRANSACTION
@crichardson
Rolling back sagas
@crichardson
Saga: Every Ti has a Ci
FAILS
T1 T2 …
C1 C2
Compensating transactions
T1 T2 C1
@crichardson
Create Order Saga - rollback
createOrder()
Insufficient credit
@crichardson
Non-compensatable actions
@crichardson
Sagas complicate API design
Synchronous API vs Asynchronous Saga
- 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
@crichardson
Revised Create Order API
createOrder()
getOrder(id)
Called periodically by client to get outcome of validation
@crichardson
Minimal impact on UI
@crichardson
Agenda
Overview of sagas
Coordinating sagas
@crichardson
How to sequence the saga
transactions?
@crichardson
Use asynchronous, broker-
based messaging
Customer
Order Service ….
Service
Message broker
vs.
@crichardson
Option #1: Choreography-based
coordination using events
Create Order
Order created Order events channel
state creditLimit
total creditReservations
@crichardson
Order Service: publishing
domain events
Create order
Publish event
@crichardson
Customer Service: consuming
domain events…
Subscribe to event
https://github.com/eventuate-tram/eventuate-tram-examples-customers-and-orders
@crichardson
Customer Service: consuming
domain events
Attempt to
Reserve credit
Publish event on
success
Publish event on
failure
@crichardson
More complex choreography example
Consumer Validated
Order
Service Inventory
Order events
channel
Inventory Reserved Service
Accounting events
channel @crichardson
Benefits and drawbacks of
choreography
Benefits Drawbacks
Simple, especially when Cyclic dependencies -
using event sourcing services listen to each
other’s events
Participants are loosely
coupled Overloads domain objects,
e.g. Order and Customer
know too much
Events = indirect way to
make something happen
https://github.com/eventuate-examples/eventuate-examples-java-customers-and-orders
Option #2: Orchestration-based saga
coordination
CreateOrderSaga
createOrder()
Invokes Invokes Invokes
Order Order
Customer
state=PENDING state=APPROVED
@crichardson
A saga (orchestrator)
is a persistent object
that
tracks the state of the saga
and
invokes the participants
@crichardson
Saga orchestrator behavior
On create: On reply:
…
CreateOrderSaga orchestrator
Create Order Customer command channel
OrderService reserveCredit()
create()
Customer
CreateOrder
create() creditLimit
Saga creditReservations
creditReserved() ...
approve()
Order
state
total… Saga reply channel
@crichardson
CreateOrderSaga definition
Saga’s Data
Sequence of
steps
Build command
to send
@crichardson
Customer Service command
handler Route command
to handler
Reserve
credit
Make reply message @crichardson
Eventuate Tram Sagas
https://github.com/eventuate-tram/eventuate-tram-sagas-
examples-customers-and-orders
@crichardson
Benefits and drawbacks of
orchestration
Benefits Drawbacks
Centralized coordination Risk of smart sagas
logic is easier to understand directing dumb services
Reduced coupling, e.g.
Customer knows less.
Simply has API
Reduces cyclic
dependencies
Agenda
Overview of sagas
Coordinating sagas
@crichardson
Lack of isolation complicates business
logic
?
Order Service Customer Service
Local transaction Local transaction
createOrder() reserveCredit()
Order
Customer
state=PENDING
Order Service
Local transaction
cancelOrder()
Time @crichardson
How to cancel a PENDING
Order?
Don’t throw an OrderNotCancellableException
@crichardson
Countermeasure Transaction
Model
http://bit.ly/semantic-acid-ctm - paywall 😥
@crichardson
Sagas are ACD
Atomicity
Saga implementation ensures that all transactions are
executed OR all are compensated
Consistency
Referential integrity within a service handled by local databases
Referential integrity across services handled by application
Durability
Durability handled by local databases
@crichardson
Lack of I anomalies
@crichardson
Outcome of
concurrent execution
!=
a sequential execution
@crichardson
Sounds scary
BUT
It’s common to relax isolation
to improve performance
@crichardson
Anomaly: Lost update
@crichardson
Anomaly: Dirty reads …
Time
@crichardson
Countermeasures for
reducing impact
*
of isolation anomalies…
T1 C1
Compensatable transactions
T2 C2
…
Pivot transaction = GO/NO GO Tn+1
….
Countermeasure: Semantic
lock Order.state =
PENDING
Order.state =
REJECTED
Compensatable transaction sets flag,
retriable transaction releases it
Order.state =
APPROVED
Countermeasure:
Commutative updates
For example:
Account.debit() compensates for Account.credit()
@crichardson
Countermeasure: Pessimistic
view
… …
Reorder saga
… …
to
Increase avail. Reduce avail. reduce risk
Cancel Order Delivery
credit credit
Won’t be compensated,
so no dirty read
@crichardson
Countermeasure: Re-read
value
Verify unchanged, possibly restart
Payment
“log” of changes:
1. reverse()
Enables operations to commute
2. authorize()
@crichardson
Countermeasure: By value
@crichardson
Agenda
Overview of sagas
Coordinating sagas
@crichardson
Use asynchronous, broker-
based messaging
Customer
Order Service ….
Service
Message broker
Service
update publish
@crichardson
Option #1: Use database
table as a message queue
@crichardson
Option #1: Use database
table as a message queue
ACID reserveCredit()
transaction
Publish
Customer Message
?
Service Publisher
Local transaction
Message
INSERT INSERT Broker
QUERY
DELETE
CUSTOMER_CREDIT_RESERVATIONS table MESSAGE table
DELETE …
@crichardson
Transaction log tailing
Order
Service
Update
Datastore
MESSAGE
ORDER tabletable
Changes
Publish
Transaction log
Transaction log Message
miner
Broker
@crichardson
Transaction log tailing
@crichardson
Transaction log tailing: benefits
and drawbacks
Benefits Drawbacks
No 2PC Obscure
@crichardson
Event sourcing: persists an
object as a sequence of events
Event table
Service
Entity Event Event Event
Entity type
id id type data
@crichardson
Guarantees:
state change
->
event is published
@crichardson
Implementing choreography-
based sagas is straightforward
@crichardson
Preserves history of domain objects
Built-in auditing
@crichardson
Summary
@crichardson
@crichardson chris@chrisrichardson.net
40%
discount
with code
ctwsaturn18
Questions?
http://learn.microservices.io @crichardson