SlideShare a Scribd company logo
The dual write problem
Jeppe Cramon - @jeppec
Cloud Create ApS
@jeppec
Essential complexity of 2 way integration
Component
Warehouse
Component
Order
Component
Billing
UI
Send-
Invoice
Save-Order
Order:Save-Order()è
call Warehouse:Reserve-Items()
call Billing:Send-Invoice()
commit()
Reserve-
Items
Local transaction between
the 3 Components
@jeppec
Let’s (micro)service’ify this
@jeppec
Accidental complexity from distributed service integration
Warehouse
Service
Order
Service
Billing
Service
UI
Send-
Invoice
Save-Order
Reserve-
Items
Local transaction between 2
local “Services”
DUAL WRITE
using Remote call
@jeppec
Microservices turns a
local functional call
into a distributed problem
@jeppec
With cross SERVICE integration
we’re bound by the laws of
distributed computing
@jeppec
The 11 Fallacies of Distributed Computing
These fallacies are assumptions architects, designers and developers
of distributed systems are likely to make. The fallacies will be proven
wrong in the long run - resulting in all sorts of troubles and pains for
the solution and architects who made the assumptions.
1. The network is reliable.
2. Latency is zero.
3. Bandwidth is infinite.
4. The network is secure.
5. Topology doesn't change.
6. There is one administrator.
7. Transport cost is zero.
8. The network is homogeneous.
9. The System is atomic/monolithic
10. The System is Finished
11. Business logic can and should be centralized
See https://arnon.me/wp-content/uploads/Files/fallacies.pdf
@jeppec
Order:Save-Order()è
call Warehouse:Reserve-Items()
call Billing:Send-Invoice()
if (Billing:Call-Failed:Too-Busy?)
Wait-A-While()
call Billing:Send-Invoice()
if (Billing:Call-Failed:Too-Busy?)
Wait-A-Little-While-Longer()
call Billing:Send-Invoice()
if (Billing:Call-Failed:IO-Error?)
Save-We-Need-Check-If-Call-Billing-Succeded-After-All
AND We-Need-To-Retry call Order:Save-Order and call Warehouse:Reserve-Items
AND Tell-Customer-That-This-Operation-Perhaps-Went-Well
if (Billing:Call-Went-Well?)
commit()
Accidental complexity from distributed service integration
Warehouse
Service
Order
Service
Billing
Service
UI
Send-
Invoice
Save-Order
Reserve-
Items
Local transaction between 2
Components
@jeppec
Remote Call
Aka. RPC/REST/SOAP/GraphQL…
@jeppec
What’s the challenge using
state mutating
Request/Response calls
between
distributed components?
@jeppec
Synchronous Request/Response
lowers our tolerance for faults
• When you get an IO error
• When servers crash or restarts
• When databases are down
• When deadlocks occurs in our databases
• Do you retry?
With synchronous Request/Response we can loose business data if there’s no automatic retry mechanism.
Also if the operation we retry isn’t idempotent* we risk having the side effect multiple times!
Client Server
Processing
The same message can be
processed more than once
*Idempotence describes the quality of an
operation in which result and state does
not change if the operation is performed
more than 1 time
Request
Processing
Duplicated Request
Duplicated Response
Response
@jeppec
Idempotence
Don’t press the button twice!
@jeppec
Ensuring
transactional
consistency
becomes much harder
@jeppec
Sales system
Sales
Update customer status (e.g. Gold customer)
Bookkeeping
Deliver goods
Delivery
system
Deliveries
Customer/
CRM system
Customers
SAP
Bookkeeping
Complete
Purchase
Transaction
Coordinator
Transactional
Resource
Request-to-Prepare
Commit
Prepared
Done
Prepare
Phase
Commit
Phase
2 Phase Commit
@jeppec
What’s wrong with distributed transactions?
• Transactions lock resources while active
• Services are autonomous
• Can’t be expected to finish within a certain time interval
• Locking keeps other transactions from completing their
job
• Locking doesn’t scale
• X Phase Commit is fragile by design
How to handle the dual
write problem?
@jeppec
Dual write problem
Order
Service
Billing
Service
Client
Send-
Invoice
Save-Order
Mutating
Remote call
Expected
transaction
boundary No simple solution (except a classic monolith)
• Local-commit-then-publish
• If the app crashes after local-
commit then the publish
operation isn’t performed
• Publish-then-local-commit
• If the local-commit fails then
we’ve already formed the publish
operation
• Billing Service may receive
published message BEFORE the
Order Service has committed
its transaction
@jeppec
Orchestration
@jeppec
Dual write problem
Orchestration / Process Manager / Saga*
Order
Service
Billing
Service
Client
Send-
Invoice
Transaction
boundary
Transaction
boundary
Save-Order
• Requires only local transactions
• Single coordinator
• Increases eventual consistency
• Requires idempotent operations
due to retries
• Requires compensations /
rollback
• Tighter coupling as the
orchestrator instructs other
services about what to do
* This isn’t the real Saga pattern
@jeppec
Choreography
@jeppec
Dual write problem
Choreography
public class OrderService {
public void handle(AcceptOrder cmd) {
orderRepository.add(new Order(cmd.orderId,
cmd.orderLines));
eventTopic.publish(new OrderAccepted(cmd.orderId,
cmd.orderLines));
}
}
public class BillingService {
public void handle(OrderAccepted cmd) {
invoiceRepository.add(new Invoice(cmd.orderId,
cmd.orderLines));
emailGateway.send(new OrderAcceptedEmail(cmd.orderId,
cmd.orderLines));
}
}
@jeppec
Dual write problem
Choreography
Order
Service
Billing
Service
Client
Send-
Invoice
Save-Order
Transaction
boundary
Transaction
boundary
• No Single coordinator, but global
system state and coordination
logic is scattered across all
participants
• Requires only local transactions
• Increases eventual consistency
• Requires idempotent operations
due to retries
• Looser coupling (if events are
used)
• Suffers from a Dual Write problem
it self
Events/Commands
Queue
@jeppec
Outbox pattern
For Choreography
@jeppec
Dual write problem
Choreography with Outbox pattern
Order
Service
Billing
Service
Client
Send-
Invoice
Save-Order
Transaction
boundary
Transaction
boundary
• You can either use a Change
Data Capture (CDC) approach
e.g. using a database Write
Ahead Log (WAL)
• Risk of CRUD events!
• Or a manual OutBox pattern
where Save-Order writes data
and the event/command into
the OutBox within the same
database. Typically requires
polling and coordination +
recovery options in a multi cluster
setup
Events/Commands
Change
Data
Capture
/
Polling
Async Push or Poll
@jeppec
Saga pattern
A failure management pattern
@jeppec
Trip reservation as a Saga
Start
Rent Car Book Hotel Reserve Flight
Cancel Hotel
Cancel Car
Book
Car Rental Hotel Rental
WorkQueue:
- Queue: “Rent Car”
- Queue: “Book Hotel”
- Queue: “Reserve Flight”
Routing slip
Flight Booking
@jeppec
Trip reservation as a Saga
Start
Rent Car Book Hotel Reserve Flight
Cancel Hotel
Cancel Car
Book Book
Car Rental Hotel Rental
WorkQueue:
- Queue: “Book Hotel”
- Queue : “Reserve Flight”
WorkStack:
- ReservationId: ABC123
Cancellation: “Cancel Car”
Routing slip Flight Booking
@jeppec
Trip reservation as a Saga
Start
Rent Car Book Hotel Reserve Flight
Cancel Hotel
Cancel Car
Book Book
Car Rental Hotel Rental
WorkQueue:
- Queue : “Reserve Flight”
WorkStack:
- Hotel ReservationId: XYZ
Cancellation: “Cancel Hotel”
- Car ReservationId: ABC123
Cancellation: “Cancel Car”
Routing slip
Book
Flight Booking
@jeppec
Trip reservation as a Saga
Start
Rent Car Book Hotel Reserve Flight
Cancel Hotel
Cancel Car
Book Book Book
Car Rental Hotel Rental
WorkStack:
- Hotel ReservationId: XYZ
Cancellation: “Cancel Hotel”
- Car ReservationId: ABC123
Cancellation: “Cancel Car”
Routing slip
Flight Booking
@jeppec
Trip reservation as a Saga
Start
Rent Car Book Hotel Reserve Flight
Cancel Hotel
Cancel Car
Book Book Book
Car Rental Hotel Rental
Cancel
WorkStack:
- Hotel ReservationId: XYZ
Cancellation: “Cancel Hotel”
- Car ReservationId: ABC123
Cancellation: “Cancel Car”
Routing slip
Flight Booking
@jeppec
Trip reservation as a Saga
Start
Rent Car Book Hotel Reserve Flight
Cancel Hotel
Cancel Car
Book Book Book
Car Rental Hotel Rental
Cancel
Cancel
WorkStack:
- Car ReservationId: ABC123
Cancellation: “Cancel Car”
Routing slip
Flight Booking
@jeppec
Trip reservation as a Saga
Start
Rent Car Book Hotel Reserve Flight
Cancel Hotel
Cancel Car
Book Book Book
Car Rental Hotel Rental
Cancel
Cancel
Cancelled
Flight Booking
@jeppec
Event Sourcing
@jeppec
Dual write problem
Choreography with Event Sourcing
Order
Service
Billing
Service
Client
Send-
Invoice
Save-Order
Transaction
boundary
Transaction
boundary
Event Store
Async
Push
or Pull
• Requires only local transactions
• Natively event driven: The Service
consumes and produces events
• Proven Audit Trail
• Flexible and adaptable
• Captures business intentions as
events
• Requires idempotent operations
@jeppec
Event Sourcing
Business-Objects/Aggregates track their own Domain Events
and derive their state from said Events
OrderCreated ProductAdded ProductAdded ProductRemoved ProductAdded OrderAccepted
Time
07:39
Time
07:40
Time
07:41
Time
07:45
Time
07:46
Time
07:50
@jeppec
Event Replaying
Type Aggregate
Identifier
GlobalOrder Event
Order
Timestamp Event
Identifier
EventType SerializedEvent
Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>…
Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>…
Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>…
Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>…
Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>…
Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>…
Order
@jeppec
Event Replaying
Type Aggregate
Identifier
GlobalOrder Event
Order
Timestamp Event
Identifier
EventType SerializedEvent
Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>…
Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>…
Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>…
Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>…
Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>…
Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>…
Order
Orderline
@jeppec
Event Replaying
Type Aggregate
Identifier
GlobalOrder Event
Order
Timestamp Event
Identifier
EventType SerializedEvent
Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>…
Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>…
Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>…
Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>…
Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>…
Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>…
Order
Orderline
Orderline
@jeppec
Event Replaying
Type Aggregate
Identifier
GlobalOrder Event
Order
Timestamp Event
Identifier
EventType SerializedEvent
Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>…
Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>…
Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>…
Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>…
Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>…
Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>…
Order
Orderline
@jeppec
Event Replaying
Type Aggregate
Identifier
GlobalOrder Event
Order
Timestamp Event
Identifier
EventType SerializedEvent
Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>…
Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>…
Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>…
Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>…
Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>…
Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>…
Order
Orderline
Orderline
@jeppec
Event Replaying
Type Aggregate
Identifier
GlobalOrder Event
Order
Timestamp Event
Identifier
EventType SerializedEvent
Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>…
Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>…
Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>…
Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>…
Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>…
Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>…
Order
Accepted: true
Orderline
Orderline
@jeppec
Client handled subscriptions
RSocketEvent
StreamSubscription
Local storage
EventStore
RSocketEvent
StreamSubscription
Local storage
EventStreamSubscription
Message
EventStreamSubscription
Message
EventStoreEventStreamPublisher
EventStoreEventStreamPublisher
Event
Event
Event Event
Supports
Single Instance
Subscriber,
which ensures
that only one
instance of
Subscriber B
has an active
subscription.
Other
instances of
the same
subscriber are
hot-standby
<<Topic Subscriber>>
Customer_Service:Some_Ac:OrderEvents
<<Topic Publisher>>
Sales_Service:OrderEvents
RSocketServer
tcp://subscribe-event-stream
A
B Subscriber B
RSocket Request/Stream
Event-Stream
Subscriber A
RSocket Request/Stream
Event-Stream
Flux<PersistedEvent> eventStream(long fromInclusiveGlobalOrder,
Option<String> subscriptionId)
@jeppec
ReactiveBus Pub/Sub
JdbcEventStores eventStores = ….
var customerAggregateType = AggregateType.from("Customer", CustomerId.class);
var customerEventStore = eventStores.getEventStoreFor(customerAggregateType);
var streamName = EventStreamName.from("CustomersStream");
reactiveBus.addEventStreamPublisher(new EventStoreEventStreamPublisher(streamName, customerEventStore, unitOfWorkFactory));
Publisher:
reactiveBus.subscribeToEventStream(
SubscriberId.from(”SalesService->CustomerEvents"),
EventStreamName.from("CustomersStream"),
EventStreamSubscriptionParameters.parameters(GlobalOrderSubscribeFromToken.fromStartOfStream()))
.doOnNext(payload -> {
System.out.println(”Received: " + e.payload.getClass() + "@" + e.globalOrder);
}).subscribe();
Subscriber:
@jeppec
Pub/Sub – Subscriber event handling
reactiveBus.subscribeToEventStream(SubscriberId.from(”SalesService->OrderEvents"),
EventStreamName.from(”OrdersStream"),
EventStreamSubscriptionParameters.parameters(GlobalOrderSubscribeFromToken.fromStartOfStream()))
.doOnNext(payload -> {
if (event instanceof OrderAdded e) {
.. = e.orderNumber;
} else if (event instanceof ProductAddedToOrder e) {
… = e.productId;
} else if (event instanceof OrderAccepted) {
…accepted = true;
}
).subscribe();
@jeppec
Pub/Sub – Subscriber event handling
@EventHandler
private void handle(OrderAdded e, EventMessage message) {
….
}
@EventHandler
private void handle(ProductAddedToOrder e) {
.…
}
@EventHandler
private void handle(OrderAccepted e) {
….
}
@jeppec
For more
see
Blog: https://cramonblog.wordpress.com/
Homepage: http://cloudcreate.dk/
Twitter: @jeppec

More Related Content

What's hot

Kafka: All an engineer needs to know
Kafka: All an engineer needs to knowKafka: All an engineer needs to know
Kafka: All an engineer needs to knowThao Huynh Quang
 
Microservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and KafkaMicroservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and KafkaAraf Karsh Hamid
 
Grokking TechTalk #33: High Concurrency Architecture at TIKI
Grokking TechTalk #33: High Concurrency Architecture at TIKIGrokking TechTalk #33: High Concurrency Architecture at TIKI
Grokking TechTalk #33: High Concurrency Architecture at TIKIGrokking VN
 
Event Driven Architecture
Event Driven ArchitectureEvent Driven Architecture
Event Driven ArchitectureStefan Norberg
 
Messaging queue - Kafka
Messaging queue - KafkaMessaging queue - Kafka
Messaging queue - KafkaMayank Bansal
 
From Lucene to Elasticsearch, a short explanation of horizontal scalability
From Lucene to Elasticsearch, a short explanation of horizontal scalabilityFrom Lucene to Elasticsearch, a short explanation of horizontal scalability
From Lucene to Elasticsearch, a short explanation of horizontal scalabilityStéphane Gamard
 
Domain Driven Design và Event Driven Architecture
Domain Driven Design và Event Driven Architecture Domain Driven Design và Event Driven Architecture
Domain Driven Design và Event Driven Architecture IT Expert Club
 
Unique ID generation in distributed systems
Unique ID generation in distributed systemsUnique ID generation in distributed systems
Unique ID generation in distributed systemsDave Gardner
 
Micro services Architecture
Micro services ArchitectureMicro services Architecture
Micro services ArchitectureAraf Karsh Hamid
 
Event-driven microservices
Event-driven microservicesEvent-driven microservices
Event-driven microservicesAndrew Schofield
 
Introduction to Apache ZooKeeper
Introduction to Apache ZooKeeperIntroduction to Apache ZooKeeper
Introduction to Apache ZooKeeperSaurav Haloi
 
Grokking Techtalk #37: Data intensive problem
 Grokking Techtalk #37: Data intensive problem Grokking Techtalk #37: Data intensive problem
Grokking Techtalk #37: Data intensive problemGrokking VN
 
MicroCPH - Managing data consistency in a microservice architecture using Sagas
MicroCPH - Managing data consistency in a microservice architecture using SagasMicroCPH - Managing data consistency in a microservice architecture using Sagas
MicroCPH - Managing data consistency in a microservice architecture using SagasChris Richardson
 
Stability Patterns for Microservices
Stability Patterns for MicroservicesStability Patterns for Microservices
Stability Patterns for Microservicespflueras
 
Apache Kafka Fundamentals for Architects, Admins and Developers
Apache Kafka Fundamentals for Architects, Admins and DevelopersApache Kafka Fundamentals for Architects, Admins and Developers
Apache Kafka Fundamentals for Architects, Admins and Developersconfluent
 
Event Driven Architecture
Event Driven ArchitectureEvent Driven Architecture
Event Driven ArchitectureLourens Naudé
 
Virtual Nodes: Rethinking Topology in Cassandra
Virtual Nodes: Rethinking Topology in CassandraVirtual Nodes: Rethinking Topology in Cassandra
Virtual Nodes: Rethinking Topology in CassandraEric Evans
 

What's hot (20)

Kafka: All an engineer needs to know
Kafka: All an engineer needs to knowKafka: All an engineer needs to know
Kafka: All an engineer needs to know
 
Microservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and KafkaMicroservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and Kafka
 
Grokking TechTalk #33: High Concurrency Architecture at TIKI
Grokking TechTalk #33: High Concurrency Architecture at TIKIGrokking TechTalk #33: High Concurrency Architecture at TIKI
Grokking TechTalk #33: High Concurrency Architecture at TIKI
 
Event Driven Architecture
Event Driven ArchitectureEvent Driven Architecture
Event Driven Architecture
 
Messaging queue - Kafka
Messaging queue - KafkaMessaging queue - Kafka
Messaging queue - Kafka
 
From Lucene to Elasticsearch, a short explanation of horizontal scalability
From Lucene to Elasticsearch, a short explanation of horizontal scalabilityFrom Lucene to Elasticsearch, a short explanation of horizontal scalability
From Lucene to Elasticsearch, a short explanation of horizontal scalability
 
Domain Driven Design và Event Driven Architecture
Domain Driven Design và Event Driven Architecture Domain Driven Design và Event Driven Architecture
Domain Driven Design và Event Driven Architecture
 
Unique ID generation in distributed systems
Unique ID generation in distributed systemsUnique ID generation in distributed systems
Unique ID generation in distributed systems
 
Micro services Architecture
Micro services ArchitectureMicro services Architecture
Micro services Architecture
 
Event-driven microservices
Event-driven microservicesEvent-driven microservices
Event-driven microservices
 
Introduction to Apache ZooKeeper
Introduction to Apache ZooKeeperIntroduction to Apache ZooKeeper
Introduction to Apache ZooKeeper
 
Grokking Techtalk #37: Data intensive problem
 Grokking Techtalk #37: Data intensive problem Grokking Techtalk #37: Data intensive problem
Grokking Techtalk #37: Data intensive problem
 
Event driven architecture
Event driven architectureEvent driven architecture
Event driven architecture
 
MicroCPH - Managing data consistency in a microservice architecture using Sagas
MicroCPH - Managing data consistency in a microservice architecture using SagasMicroCPH - Managing data consistency in a microservice architecture using Sagas
MicroCPH - Managing data consistency in a microservice architecture using Sagas
 
Stability Patterns for Microservices
Stability Patterns for MicroservicesStability Patterns for Microservices
Stability Patterns for Microservices
 
Apache Kafka Fundamentals for Architects, Admins and Developers
Apache Kafka Fundamentals for Architects, Admins and DevelopersApache Kafka Fundamentals for Architects, Admins and Developers
Apache Kafka Fundamentals for Architects, Admins and Developers
 
Apache Kafka
Apache KafkaApache Kafka
Apache Kafka
 
Event Driven Architecture
Event Driven ArchitectureEvent Driven Architecture
Event Driven Architecture
 
Virtual Nodes: Rethinking Topology in Cassandra
Virtual Nodes: Rethinking Topology in CassandraVirtual Nodes: Rethinking Topology in Cassandra
Virtual Nodes: Rethinking Topology in Cassandra
 
Apache ZooKeeper
Apache ZooKeeperApache ZooKeeper
Apache ZooKeeper
 

Similar to The Dual write problem

Event Driven Architecture (Integration Tech Event 2019)
Event Driven Architecture (Integration Tech Event 2019)Event Driven Architecture (Integration Tech Event 2019)
Event Driven Architecture (Integration Tech Event 2019)Jeppe Cramon
 
Should you be using an event driven architecture - IDA IT (short version)
Should you be using an event driven architecture - IDA IT (short version)Should you be using an event driven architecture - IDA IT (short version)
Should you be using an event driven architecture - IDA IT (short version)Jeppe Cramon
 
What 5 years of implementation microservices has taught me
What 5 years of implementation microservices has taught meWhat 5 years of implementation microservices has taught me
What 5 years of implementation microservices has taught meJeppe Cramon
 
Long running processes in DDD
Long running processes in DDDLong running processes in DDD
Long running processes in DDDBernd Ruecker
 
Inventing the future Business Programming Language
Inventing the future  Business Programming LanguageInventing the future  Business Programming Language
Inventing the future Business Programming LanguageESUG
 
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...The Art of The Event Streaming Application: Streams, Stream Processors and Sc...
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...confluent
 
Kakfa summit london 2019 - the art of the event-streaming app
Kakfa summit london 2019 - the art of the event-streaming appKakfa summit london 2019 - the art of the event-streaming app
Kakfa summit london 2019 - the art of the event-streaming appNeil Avery
 
Sap overview posted by Parikshit Sanghavi
Sap overview posted by Parikshit SanghaviSap overview posted by Parikshit Sanghavi
Sap overview posted by Parikshit SanghaviParikshit Sanghavi
 
Should you be using an event driven architecture?
Should you be using an event driven architecture?Should you be using an event driven architecture?
Should you be using an event driven architecture?Jeppe Cramon
 
Event Driven Architectures
Event Driven ArchitecturesEvent Driven Architectures
Event Driven ArchitecturesAvinash Ramineni
 
CQRS + Event Sourcing
CQRS + Event SourcingCQRS + Event Sourcing
CQRS + Event SourcingMike Bild
 
Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...
Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...
Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...Lucas Jellema
 
Complex Event Processing: What?, Why?, How?
Complex Event Processing: What?, Why?, How?Complex Event Processing: What?, Why?, How?
Complex Event Processing: What?, Why?, How?Fabien Coppens
 
Data Microservices with Spring Cloud
Data Microservices with Spring CloudData Microservices with Spring Cloud
Data Microservices with Spring CloudOrkhan Gasimov
 
Event Driven Architectures - Phoenix Java Users Group 2013
Event Driven Architectures - Phoenix Java Users Group 2013Event Driven Architectures - Phoenix Java Users Group 2013
Event Driven Architectures - Phoenix Java Users Group 2013clairvoyantllc
 
SBJUG - Building Beautiful Batch Jobs
SBJUG - Building Beautiful Batch JobsSBJUG - Building Beautiful Batch Jobs
SBJUG - Building Beautiful Batch Jobsstephenbhadran
 
Microservices in the Apache Kafka Ecosystem
Microservices in the Apache Kafka EcosystemMicroservices in the Apache Kafka Ecosystem
Microservices in the Apache Kafka Ecosystemconfluent
 
Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...
Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...
Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...confluent
 
2-1 Remember the Help Desk with AFCU - Jared Flanders, Final
2-1 Remember the Help Desk with AFCU - Jared Flanders, Final2-1 Remember the Help Desk with AFCU - Jared Flanders, Final
2-1 Remember the Help Desk with AFCU - Jared Flanders, FinalJared Flanders
 

Similar to The Dual write problem (20)

Event Driven Architecture (Integration Tech Event 2019)
Event Driven Architecture (Integration Tech Event 2019)Event Driven Architecture (Integration Tech Event 2019)
Event Driven Architecture (Integration Tech Event 2019)
 
Should you be using an event driven architecture - IDA IT (short version)
Should you be using an event driven architecture - IDA IT (short version)Should you be using an event driven architecture - IDA IT (short version)
Should you be using an event driven architecture - IDA IT (short version)
 
What 5 years of implementation microservices has taught me
What 5 years of implementation microservices has taught meWhat 5 years of implementation microservices has taught me
What 5 years of implementation microservices has taught me
 
Long running processes in DDD
Long running processes in DDDLong running processes in DDD
Long running processes in DDD
 
Inventing the future Business Programming Language
Inventing the future  Business Programming LanguageInventing the future  Business Programming Language
Inventing the future Business Programming Language
 
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...The Art of The Event Streaming Application: Streams, Stream Processors and Sc...
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...
 
Kakfa summit london 2019 - the art of the event-streaming app
Kakfa summit london 2019 - the art of the event-streaming appKakfa summit london 2019 - the art of the event-streaming app
Kakfa summit london 2019 - the art of the event-streaming app
 
Sap overview posted by Parikshit Sanghavi
Sap overview posted by Parikshit SanghaviSap overview posted by Parikshit Sanghavi
Sap overview posted by Parikshit Sanghavi
 
Sapbasic
SapbasicSapbasic
Sapbasic
 
Should you be using an event driven architecture?
Should you be using an event driven architecture?Should you be using an event driven architecture?
Should you be using an event driven architecture?
 
Event Driven Architectures
Event Driven ArchitecturesEvent Driven Architectures
Event Driven Architectures
 
CQRS + Event Sourcing
CQRS + Event SourcingCQRS + Event Sourcing
CQRS + Event Sourcing
 
Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...
Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...
Don't call us - we'll push - on cross tier push architecture (NLJUG JFall 201...
 
Complex Event Processing: What?, Why?, How?
Complex Event Processing: What?, Why?, How?Complex Event Processing: What?, Why?, How?
Complex Event Processing: What?, Why?, How?
 
Data Microservices with Spring Cloud
Data Microservices with Spring CloudData Microservices with Spring Cloud
Data Microservices with Spring Cloud
 
Event Driven Architectures - Phoenix Java Users Group 2013
Event Driven Architectures - Phoenix Java Users Group 2013Event Driven Architectures - Phoenix Java Users Group 2013
Event Driven Architectures - Phoenix Java Users Group 2013
 
SBJUG - Building Beautiful Batch Jobs
SBJUG - Building Beautiful Batch JobsSBJUG - Building Beautiful Batch Jobs
SBJUG - Building Beautiful Batch Jobs
 
Microservices in the Apache Kafka Ecosystem
Microservices in the Apache Kafka EcosystemMicroservices in the Apache Kafka Ecosystem
Microservices in the Apache Kafka Ecosystem
 
Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...
Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...
Event Sourcing, Stream Processing and Serverless (Benjamin Stopford, Confluen...
 
2-1 Remember the Help Desk with AFCU - Jared Flanders, Final
2-1 Remember the Help Desk with AFCU - Jared Flanders, Final2-1 Remember the Help Desk with AFCU - Jared Flanders, Final
2-1 Remember the Help Desk with AFCU - Jared Flanders, Final
 

Recently uploaded

ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupCatarinaPereira64715
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor TurskyiFwdays
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonDianaGray10
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Product School
 
In-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsIn-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsExpeed Software
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomCzechDreamin
 
UiPath Test Automation using UiPath Test Suite series, part 1
UiPath Test Automation using UiPath Test Suite series, part 1UiPath Test Automation using UiPath Test Suite series, part 1
UiPath Test Automation using UiPath Test Suite series, part 1DianaGray10
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...Product School
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxAbida Shariff
 
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀DianaGray10
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Thierry Lestable
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Julian Hyde
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualityInflectra
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Jeffrey Haguewood
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2DianaGray10
 
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...CzechDreamin
 
What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024Stephanie Beckett
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Product School
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Product School
 
Introduction to Open Source RAG and RAG Evaluation
Introduction to Open Source RAG and RAG EvaluationIntroduction to Open Source RAG and RAG Evaluation
Introduction to Open Source RAG and RAG EvaluationZilliz
 

Recently uploaded (20)

ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
In-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsIn-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT Professionals
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
 
UiPath Test Automation using UiPath Test Suite series, part 1
UiPath Test Automation using UiPath Test Suite series, part 1UiPath Test Automation using UiPath Test Suite series, part 1
UiPath Test Automation using UiPath Test Suite series, part 1
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2
 
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
 
What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Introduction to Open Source RAG and RAG Evaluation
Introduction to Open Source RAG and RAG EvaluationIntroduction to Open Source RAG and RAG Evaluation
Introduction to Open Source RAG and RAG Evaluation
 

The Dual write problem

  • 1. The dual write problem Jeppe Cramon - @jeppec Cloud Create ApS
  • 2. @jeppec Essential complexity of 2 way integration Component Warehouse Component Order Component Billing UI Send- Invoice Save-Order Order:Save-Order()è call Warehouse:Reserve-Items() call Billing:Send-Invoice() commit() Reserve- Items Local transaction between the 3 Components
  • 4. @jeppec Accidental complexity from distributed service integration Warehouse Service Order Service Billing Service UI Send- Invoice Save-Order Reserve- Items Local transaction between 2 local “Services” DUAL WRITE using Remote call
  • 5. @jeppec Microservices turns a local functional call into a distributed problem
  • 6. @jeppec With cross SERVICE integration we’re bound by the laws of distributed computing
  • 7. @jeppec The 11 Fallacies of Distributed Computing These fallacies are assumptions architects, designers and developers of distributed systems are likely to make. The fallacies will be proven wrong in the long run - resulting in all sorts of troubles and pains for the solution and architects who made the assumptions. 1. The network is reliable. 2. Latency is zero. 3. Bandwidth is infinite. 4. The network is secure. 5. Topology doesn't change. 6. There is one administrator. 7. Transport cost is zero. 8. The network is homogeneous. 9. The System is atomic/monolithic 10. The System is Finished 11. Business logic can and should be centralized See https://arnon.me/wp-content/uploads/Files/fallacies.pdf
  • 8. @jeppec Order:Save-Order()è call Warehouse:Reserve-Items() call Billing:Send-Invoice() if (Billing:Call-Failed:Too-Busy?) Wait-A-While() call Billing:Send-Invoice() if (Billing:Call-Failed:Too-Busy?) Wait-A-Little-While-Longer() call Billing:Send-Invoice() if (Billing:Call-Failed:IO-Error?) Save-We-Need-Check-If-Call-Billing-Succeded-After-All AND We-Need-To-Retry call Order:Save-Order and call Warehouse:Reserve-Items AND Tell-Customer-That-This-Operation-Perhaps-Went-Well if (Billing:Call-Went-Well?) commit() Accidental complexity from distributed service integration Warehouse Service Order Service Billing Service UI Send- Invoice Save-Order Reserve- Items Local transaction between 2 Components
  • 10. @jeppec What’s the challenge using state mutating Request/Response calls between distributed components?
  • 11. @jeppec Synchronous Request/Response lowers our tolerance for faults • When you get an IO error • When servers crash or restarts • When databases are down • When deadlocks occurs in our databases • Do you retry? With synchronous Request/Response we can loose business data if there’s no automatic retry mechanism. Also if the operation we retry isn’t idempotent* we risk having the side effect multiple times! Client Server Processing The same message can be processed more than once *Idempotence describes the quality of an operation in which result and state does not change if the operation is performed more than 1 time Request Processing Duplicated Request Duplicated Response Response
  • 14. @jeppec Sales system Sales Update customer status (e.g. Gold customer) Bookkeeping Deliver goods Delivery system Deliveries Customer/ CRM system Customers SAP Bookkeeping Complete Purchase Transaction Coordinator Transactional Resource Request-to-Prepare Commit Prepared Done Prepare Phase Commit Phase 2 Phase Commit
  • 15. @jeppec What’s wrong with distributed transactions? • Transactions lock resources while active • Services are autonomous • Can’t be expected to finish within a certain time interval • Locking keeps other transactions from completing their job • Locking doesn’t scale • X Phase Commit is fragile by design
  • 16. How to handle the dual write problem?
  • 17. @jeppec Dual write problem Order Service Billing Service Client Send- Invoice Save-Order Mutating Remote call Expected transaction boundary No simple solution (except a classic monolith) • Local-commit-then-publish • If the app crashes after local- commit then the publish operation isn’t performed • Publish-then-local-commit • If the local-commit fails then we’ve already formed the publish operation • Billing Service may receive published message BEFORE the Order Service has committed its transaction
  • 19. @jeppec Dual write problem Orchestration / Process Manager / Saga* Order Service Billing Service Client Send- Invoice Transaction boundary Transaction boundary Save-Order • Requires only local transactions • Single coordinator • Increases eventual consistency • Requires idempotent operations due to retries • Requires compensations / rollback • Tighter coupling as the orchestrator instructs other services about what to do * This isn’t the real Saga pattern
  • 21. @jeppec Dual write problem Choreography public class OrderService { public void handle(AcceptOrder cmd) { orderRepository.add(new Order(cmd.orderId, cmd.orderLines)); eventTopic.publish(new OrderAccepted(cmd.orderId, cmd.orderLines)); } } public class BillingService { public void handle(OrderAccepted cmd) { invoiceRepository.add(new Invoice(cmd.orderId, cmd.orderLines)); emailGateway.send(new OrderAcceptedEmail(cmd.orderId, cmd.orderLines)); } }
  • 22. @jeppec Dual write problem Choreography Order Service Billing Service Client Send- Invoice Save-Order Transaction boundary Transaction boundary • No Single coordinator, but global system state and coordination logic is scattered across all participants • Requires only local transactions • Increases eventual consistency • Requires idempotent operations due to retries • Looser coupling (if events are used) • Suffers from a Dual Write problem it self Events/Commands Queue
  • 24. @jeppec Dual write problem Choreography with Outbox pattern Order Service Billing Service Client Send- Invoice Save-Order Transaction boundary Transaction boundary • You can either use a Change Data Capture (CDC) approach e.g. using a database Write Ahead Log (WAL) • Risk of CRUD events! • Or a manual OutBox pattern where Save-Order writes data and the event/command into the OutBox within the same database. Typically requires polling and coordination + recovery options in a multi cluster setup Events/Commands Change Data Capture / Polling Async Push or Poll
  • 25. @jeppec Saga pattern A failure management pattern
  • 26. @jeppec Trip reservation as a Saga Start Rent Car Book Hotel Reserve Flight Cancel Hotel Cancel Car Book Car Rental Hotel Rental WorkQueue: - Queue: “Rent Car” - Queue: “Book Hotel” - Queue: “Reserve Flight” Routing slip Flight Booking
  • 27. @jeppec Trip reservation as a Saga Start Rent Car Book Hotel Reserve Flight Cancel Hotel Cancel Car Book Book Car Rental Hotel Rental WorkQueue: - Queue: “Book Hotel” - Queue : “Reserve Flight” WorkStack: - ReservationId: ABC123 Cancellation: “Cancel Car” Routing slip Flight Booking
  • 28. @jeppec Trip reservation as a Saga Start Rent Car Book Hotel Reserve Flight Cancel Hotel Cancel Car Book Book Car Rental Hotel Rental WorkQueue: - Queue : “Reserve Flight” WorkStack: - Hotel ReservationId: XYZ Cancellation: “Cancel Hotel” - Car ReservationId: ABC123 Cancellation: “Cancel Car” Routing slip Book Flight Booking
  • 29. @jeppec Trip reservation as a Saga Start Rent Car Book Hotel Reserve Flight Cancel Hotel Cancel Car Book Book Book Car Rental Hotel Rental WorkStack: - Hotel ReservationId: XYZ Cancellation: “Cancel Hotel” - Car ReservationId: ABC123 Cancellation: “Cancel Car” Routing slip Flight Booking
  • 30. @jeppec Trip reservation as a Saga Start Rent Car Book Hotel Reserve Flight Cancel Hotel Cancel Car Book Book Book Car Rental Hotel Rental Cancel WorkStack: - Hotel ReservationId: XYZ Cancellation: “Cancel Hotel” - Car ReservationId: ABC123 Cancellation: “Cancel Car” Routing slip Flight Booking
  • 31. @jeppec Trip reservation as a Saga Start Rent Car Book Hotel Reserve Flight Cancel Hotel Cancel Car Book Book Book Car Rental Hotel Rental Cancel Cancel WorkStack: - Car ReservationId: ABC123 Cancellation: “Cancel Car” Routing slip Flight Booking
  • 32. @jeppec Trip reservation as a Saga Start Rent Car Book Hotel Reserve Flight Cancel Hotel Cancel Car Book Book Book Car Rental Hotel Rental Cancel Cancel Cancelled Flight Booking
  • 34. @jeppec Dual write problem Choreography with Event Sourcing Order Service Billing Service Client Send- Invoice Save-Order Transaction boundary Transaction boundary Event Store Async Push or Pull • Requires only local transactions • Natively event driven: The Service consumes and produces events • Proven Audit Trail • Flexible and adaptable • Captures business intentions as events • Requires idempotent operations
  • 35. @jeppec Event Sourcing Business-Objects/Aggregates track their own Domain Events and derive their state from said Events OrderCreated ProductAdded ProductAdded ProductRemoved ProductAdded OrderAccepted Time 07:39 Time 07:40 Time 07:41 Time 07:45 Time 07:46 Time 07:50
  • 36. @jeppec Event Replaying Type Aggregate Identifier GlobalOrder Event Order Timestamp Event Identifier EventType SerializedEvent Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>… Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>… Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>… Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>… Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>… Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>… Order
  • 37. @jeppec Event Replaying Type Aggregate Identifier GlobalOrder Event Order Timestamp Event Identifier EventType SerializedEvent Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>… Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>… Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>… Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>… Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>… Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>… Order Orderline
  • 38. @jeppec Event Replaying Type Aggregate Identifier GlobalOrder Event Order Timestamp Event Identifier EventType SerializedEvent Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>… Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>… Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>… Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>… Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>… Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>… Order Orderline Orderline
  • 39. @jeppec Event Replaying Type Aggregate Identifier GlobalOrder Event Order Timestamp Event Identifier EventType SerializedEvent Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>… Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>… Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>… Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>… Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>… Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>… Order Orderline
  • 40. @jeppec Event Replaying Type Aggregate Identifier GlobalOrder Event Order Timestamp Event Identifier EventType SerializedEvent Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>… Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>… Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>… Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>… Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>… Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>… Order Orderline Orderline
  • 41. @jeppec Event Replaying Type Aggregate Identifier GlobalOrder Event Order Timestamp Event Identifier EventType SerializedEvent Order 14237 100 0 2014-01-06 7:39 {Guid-1} OrderCreated <serialized event>… Order 14237 101 1 2014-01-06 7:40 {Guid-2} ProductAdded <serialized event>… Order 14237 102 2 2014-01-06 7:41 {Guid-3} ProductAdded <serialized event>… Order 14237 103 3 2014-01-06 7:45 {Guid-4} ProductRemoved <serialized event>… Order 14237 104 4 2014-01-06 7:46 {Guid-5} ProductAdded <serialized event>… Order 14237 105 5 2014-01-06 7:50 {Guid-6} OrderAccepted <serialized event>… Order Accepted: true Orderline Orderline
  • 42. @jeppec Client handled subscriptions RSocketEvent StreamSubscription Local storage EventStore RSocketEvent StreamSubscription Local storage EventStreamSubscription Message EventStreamSubscription Message EventStoreEventStreamPublisher EventStoreEventStreamPublisher Event Event Event Event Supports Single Instance Subscriber, which ensures that only one instance of Subscriber B has an active subscription. Other instances of the same subscriber are hot-standby <<Topic Subscriber>> Customer_Service:Some_Ac:OrderEvents <<Topic Publisher>> Sales_Service:OrderEvents RSocketServer tcp://subscribe-event-stream A B Subscriber B RSocket Request/Stream Event-Stream Subscriber A RSocket Request/Stream Event-Stream Flux<PersistedEvent> eventStream(long fromInclusiveGlobalOrder, Option<String> subscriptionId)
  • 43. @jeppec ReactiveBus Pub/Sub JdbcEventStores eventStores = …. var customerAggregateType = AggregateType.from("Customer", CustomerId.class); var customerEventStore = eventStores.getEventStoreFor(customerAggregateType); var streamName = EventStreamName.from("CustomersStream"); reactiveBus.addEventStreamPublisher(new EventStoreEventStreamPublisher(streamName, customerEventStore, unitOfWorkFactory)); Publisher: reactiveBus.subscribeToEventStream( SubscriberId.from(”SalesService->CustomerEvents"), EventStreamName.from("CustomersStream"), EventStreamSubscriptionParameters.parameters(GlobalOrderSubscribeFromToken.fromStartOfStream())) .doOnNext(payload -> { System.out.println(”Received: " + e.payload.getClass() + "@" + e.globalOrder); }).subscribe(); Subscriber:
  • 44. @jeppec Pub/Sub – Subscriber event handling reactiveBus.subscribeToEventStream(SubscriberId.from(”SalesService->OrderEvents"), EventStreamName.from(”OrdersStream"), EventStreamSubscriptionParameters.parameters(GlobalOrderSubscribeFromToken.fromStartOfStream())) .doOnNext(payload -> { if (event instanceof OrderAdded e) { .. = e.orderNumber; } else if (event instanceof ProductAddedToOrder e) { … = e.productId; } else if (event instanceof OrderAccepted) { …accepted = true; } ).subscribe();
  • 45. @jeppec Pub/Sub – Subscriber event handling @EventHandler private void handle(OrderAdded e, EventMessage message) { …. } @EventHandler private void handle(ProductAddedToOrder e) { .… } @EventHandler private void handle(OrderAccepted e) { …. }