Event sourcing and CQRS from the trenches SIDNEY SHEK ARCHITECT - - PowerPoint PPT Presentation

event sourcing and cqrs from the trenches
SMART_READER_LITE
LIVE PREVIEW

Event sourcing and CQRS from the trenches SIDNEY SHEK ARCHITECT - - PowerPoint PPT Presentation

Event sourcing and CQRS from the trenches SIDNEY SHEK ARCHITECT ATLASSIAN @SIDNEYSHEK Universe of Users users Id Name Username APIKey 1 Homer homer d0a 2 Bart bart f00 3 Maggie maggie baa Universe of Users


slide-1
SLIDE 1

SIDNEY SHEK • ARCHITECT • ATLASSIAN • @SIDNEYSHEK

Event sourcing and CQRS from the trenches

slide-2
SLIDE 2

Universe of Users

Id Name Username APIKey 1 Homer homer d0a 2 Bart bart f00 3 Maggie maggie baa users

slide-3
SLIDE 3

Universe of Users

Id Name Username APIKey 1 Homer homer d0a 2 Bart bart f00 3 Lisa Jr maggie baa users

slide-4
SLIDE 4

Universe of Users

Id Name Username APIKey 1 Homer homers d0a 2 Bart bart f00 3 Lisa Jr maggie baa users

slide-5
SLIDE 5

Universe of Users

Id Name Username APIKey 1 Homer homer d0a 2 Bart bart f00 3 Maggie maggie baa users events Seq Event Time 123 SetUsername(3, Maggie)

slide-6
SLIDE 6

Universe of Users

Id Name Username APIKey 1 Homer homer d0a 2 Bart bart f00 3 Lisa Jr maggie baa users events Seq Event Time 123 SetUsername(3, Maggie) 124 SetName(3, Lisa Jr) 10

slide-7
SLIDE 7

Universe of Users

Id Name Username APIKey 1 Homer homers d0a 2 Bart bart f00 3 Lisa Jr maggie baa users events Seq Event Time 123 SetUsername(3, Maggie) 124 SetName(3, Lisa Jr) 10 125 SetUsername(1, homers) 15

slide-8
SLIDE 8

Universe of Users

Id Name Username APIKey 1 Homer homers d0a 2 Bart bart f00 3 Lisa Jr maggie baa users events Seq Event Time 123 SetUsername(3, Maggie) 124 SetName(3, Lisa Jr) 10 125 SetUsername(1, homers) 15 Id Name Derived 1 Homer Homer1 2 Bart Bart2 3 Lisa Jr Lisa Jr3 users_new

slide-9
SLIDE 9

Universe of Users

Id Name Username APIKey 1 Homer homers d0a 2 Bart bart f00 3 Lisa Jr maggie baa users events Seq Event Time 123 SetUsername(3, Maggie) 124 SetName(3, Lisa Jr) 10 125 SetUsername(1, homers) 15 Id Name Derived 1 Homer Homer1 2 Bart Bart2 3 Lisa Jr Lisa Jr3 users_new

slide-10
SLIDE 10

Our Identity System requirements

slide-11
SLIDE 11

Our Identity System requirements

  • Users, groups and memberships
slide-12
SLIDE 12

Our Identity System requirements

  • Users, groups and memberships
  • Searching for users
slide-13
SLIDE 13

Our Identity System requirements

  • Users, groups and memberships
  • Searching for users
  • Retrieve by email
slide-14
SLIDE 14

Our Identity System requirements

  • Users, groups and memberships
  • Searching for users
  • Retrieve by email
  • High volume low latency reads
slide-15
SLIDE 15

Our Identity System requirements

  • Users, groups and memberships
  • Searching for users
  • Retrieve by email
  • Incremental synchronisation
  • High volume low latency reads
slide-16
SLIDE 16

Our Identity System requirements

  • Users, groups and memberships
  • Searching for users
  • Retrieve by email
  • Incremental synchronisation
  • Audit trails for changes
  • High volume low latency reads
slide-17
SLIDE 17

Our Identity System requirements

  • Users, groups and memberships
  • Searching for users
  • Retrieve by email
  • Incremental synchronisation
  • Audit trails for changes
  • High volume low latency reads
  • Highly available
  • Disaster recovery
  • Zero-downtime upgrades
slide-18
SLIDE 18

Our Identity System requirements

  • Users, groups and memberships
  • Searching for users
  • Retrieve by email
  • Incremental synchronisation
  • Audit trails for changes
  • High volume low latency reads
  • Highly available
  • Disaster recovery
  • Zero-downtime upgrades
  • Testing with production-like data
slide-19
SLIDE 19

Evolving the architecture

slide-20
SLIDE 20

DynamoDB

SaveAPI Core app EventStream Services

REST calls

e.g. Add User

Query views Query views Query views

slide-21
SLIDE 21

Command Query Responsibility Segregation

slide-22
SLIDE 22

Domain

(bus. logic)

Database UI

User User Search for users Users and groups

slide-23
SLIDE 23

Command

(write logic)

Database UI

User

Query views Query views Query views

User Search for users Users and groups

slide-24
SLIDE 24

Command

(write logic)

UI

User

Query views Query views Query views

User Search for users Users and groups

ElasticSearch

slide-25
SLIDE 25

DynamoDB

Commands Core app EventStream Services

REST calls

e.g. Add User

Query views Query views Query sync EventStream EventStream Query views

slide-26
SLIDE 26

DynamoDB

Commands Core app EventStream Services

REST calls

e.g. Add User

Query views Query views Query sync EventStream EventStream Query views

Kinesis

Lambda ElasticSearch

Events

slide-27
SLIDE 27

DynamoDB

Commands Groups EventStream Services

REST calls

e.g. Add User

Query views Query views Query sync EventStream EventStream Query views

Kinesis

Lambda

Platform Events

Kinesis

External Events

Event Txf

Users

slide-28
SLIDE 28

Events as an API

slide-29
SLIDE 29

UserAdded(id, name, email1)

Insert / Update Delta ‘Set’ events

UserUpdated(id, email = Some(email)) UserNameSet(id, name) UserEmailSet(id, email1) UserEmailSet(id, email2) Fits nicely with CRUD + PATCH Assume insert before update Encourages idempotent processing Minimally sized events to avoid conflict Single code path for query sync

vs

slide-30
SLIDE 30

Sharding for throughput

Multiple streams Single stream

Transactions and consistent data resolution Better availability vs consistency compromise

slide-31
SLIDE 31

Rules for splitting streams

  • 1. Place independent events on different streams
slide-32
SLIDE 32

Rules for splitting streams

  • 1. Place independent events on different streams
  • 2. Split streams by event type and unique Id
slide-33
SLIDE 33

Rules for splitting streams

  • 1. Place independent events on different streams
  • 2. Split streams by event type and unique Id
  • 3. Identify the ‘transactions’ you really need
slide-34
SLIDE 34

Rules for splitting streams

  • 1. Place independent events on different streams
  • 2. Split streams by event type and unique Id
  • 3. Identify the ‘transactions’ you really need
  • 4. Use hierarchical streams to maximise number of streams
slide-35
SLIDE 35

Rules for splitting streams

  • 1. Place independent events on different streams
  • 2. Split streams by event type and unique Id
  • 3. Identify the ‘transactions’ you really need
  • 4. Use hierarchical streams to maximise number of streams
  • 5. Splitting and joining streams later is possible
slide-36
SLIDE 36

But… no guaranteed order between streams

slide-37
SLIDE 37

Query views get populated eventually

slide-38
SLIDE 38

Query views get populated eventually

  • A field should only be updated by a single event stream
slide-39
SLIDE 39

Query views get populated eventually

  • A field should only be updated by a single event stream
  • No foreign key constraints
slide-40
SLIDE 40

Query views get populated eventually

  • A field should only be updated by a single event stream
  • No foreign key constraints
  • In general, unique or data constraints ‘enforced’ on write
slide-41
SLIDE 41

Let go of transactions and consistency

slide-42
SLIDE 42

Why do we need transactions?

slide-43
SLIDE 43

Why do we need transactions?

  • Enforce business constraints e.g. uniqueness
slide-44
SLIDE 44

Why do we need transactions?

  • Enforce business constraints e.g. uniqueness
  • Guaranteed to see what I just wrote
slide-45
SLIDE 45

Write and Read Consistency

slide-46
SLIDE 46

But CAP theorem…

slide-47
SLIDE 47

CAP or PACELC?

slide-48
SLIDE 48

CAP or PACELC?

During a network Partition, choose between Availability versus Consistency

slide-49
SLIDE 49

CAP or PACELC?

During a network Partition, choose between Availability versus Consistency Else choose between Latency versus Consistency

slide-50
SLIDE 50

There is a middle ground…

slide-51
SLIDE 51
  • 1. Read at seq X
  • 2. Run business rule
  • 3. Stream must be at X to write

Check-and-Set writes Optional forced reads

Query view must be at stream seq X Potential false positives Enforce timed waits Do not use as default Potential increased latency Smaller streams alleviate problems Potentially conflicting events on same stream

slide-52
SLIDE 52

Tokens to emulate transactions and consistency

User: homer (id 4)

All Users: Seq 100 User 4: Seq 23

slide-53
SLIDE 53

Tokens to emulate transactions and consistency

  • Returned on read and write via ETag

User: homer (id 4)

All Users: Seq 100 User 4: Seq 23

slide-54
SLIDE 54

Tokens to emulate transactions and consistency

  • Returned on read and write via ETag
  • Pass as request header for:

User: homer (id 4)

All Users: Seq 100 User 4: Seq 23

slide-55
SLIDE 55

Tokens to emulate transactions and consistency

  • Returned on read and write via ETag
  • Pass as request header for:
  • Condition write (‘transaction’)

User: homer (id 4)

All Users: Seq 100 User 4: Seq 23

slide-56
SLIDE 56

Tokens to emulate transactions and consistency

  • Returned on read and write via ETag
  • Pass as request header for:
  • Condition write (‘transaction’)
  • Force query view update (‘consistency’)

User: homer (id 4)

All Users: Seq 100 User 4: Seq 23

slide-57
SLIDE 57

Tokens to emulate transactions and consistency

  • Returned on read and write via ETag
  • Pass as request header for:
  • Condition write (‘transaction’)
  • Force query view update (‘consistency’)
  • Caching

User: homer (id 4)

All Users: Seq 100 User 4: Seq 23

slide-58
SLIDE 58

Using tokens to enforce state

Client Core App

slide-59
SLIDE 59

Using tokens to enforce state

Client Core App

Create User A

slide-60
SLIDE 60

Using tokens to enforce state

Client Core App

Create User A Token TU1

slide-61
SLIDE 61

Using tokens to enforce state

Client Core App

Create User A Create Group B Token TU1

slide-62
SLIDE 62

Using tokens to enforce state

Client Core App

Create User A Create Group B Token TU1 Token TG1

slide-63
SLIDE 63

Using tokens to enforce state

Client Core App

Create User A Create Group B Add User A to Group B (tokens TU1, TG1) Token TU1 Token TG1

slide-64
SLIDE 64

Using tokens to enforce state

Client Core App

Create User A Create Group B Add User A to Group B (tokens TU1, TG1) Force query view to TU1, TG1 Token TU1 Token TG1

slide-65
SLIDE 65

Using tokens to enforce state

Client Core App

Create User A Create Group B Add User A to Group B (tokens TU1, TG1) Force query view to TU1, TG1 Token TU1 Token TG1 Token TG2

slide-66
SLIDE 66

Conflict resolution instead of transactions

slide-67
SLIDE 67

Resolve conflicts on query

  • Conflicting events on same stream

Handles multi-region writes Needs to be implemented on all query nodes No falsely failed transactions Potential temporary glitches

  • Defined resolution algorithm on replay
  • e.g. Last Write Wins
  • Convergent/Commutative Replicated Data Types

(CRDTs)

More resilient query views

slide-68
SLIDE 68

Summary

slide-69
SLIDE 69

Key takeaways

  • Start small and challenge everything!
slide-70
SLIDE 70

Key takeaways

  • Start small and challenge everything!
  • Incremental architecture for incremental demos
slide-71
SLIDE 71

Key takeaways

  • Start small and challenge everything!
  • Incremental architecture for incremental demos
  • Think “Events as an API”
slide-72
SLIDE 72

Key takeaways

  • Start small and challenge everything!
  • Incremental architecture for incremental demos
  • Think “Events as an API”
  • Accept weaker transactions and eventual consistency
slide-73
SLIDE 73

“We should using event sourcing more than we do”

Martin Fowler (very loosely paraphrased)

slide-74
SLIDE 74

event sourcing lib:

bitbucket.org/atlassianlabs/eventsrc