Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

The Good, The Bad and The Ugly of Event Sourcing

511 Aufrufe

Veröffentlicht am

In 2009, I first learned about Event Sourcing and Command Query Responsibility Seggregation (CQRS) at a training Greg Young gave in Utrecht, The Netherlands. I remember being awed by the scalability and architectural simplicity those styles provided. However, I also remembered the technical complexity that comes with it. In 2012, I was in charge of transitioning a CQRS-based system to Event Sourcing. I knew it would be non-trivial, but boy was I in for a surprise. So, over the last four years, I've experienced first-hand how a large group of developers had to deal with the transition. It's a brilliant solution for high-performance or complex business systems, but you need to be aware that this also introduces challenges most people don't tell you about. In this talk, I'd like to share you some of the most powerful benefits of ES, but also show you the flipside of the coin and cover some of the smaller and bigger challenges you'll run into it. Again, I love it and would apply it again without any doubt, but I really want you to understand the trade-offs before you jump on the Event Sourcing train.

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

The Good, The Bad and The Ugly of Event Sourcing

  1. 1. Dennis Doomen | @ddoomen | Aviva Solutions | The Continuous Improver
  2. 2. Application Command Service Correct Customer Email Handler Customer Unit of Work Projector Data Access Layer Read Database Write Database CorrectCustomerEmailCommand HTTP API / In-process invocation Get<Customer>(identity) Correct Email Event Store Load(events) Apply Get changes CustomerEmailCorrectedEvent Submit changes History Dennis Doomen | @ddoomen | The Continuous Improver NES Aggregates.NET SimpleDomain NStore EventStore NEventStore (*) SQLStreamStore (*) NStore NES Marten Handelier Brighter MediatR (*) Projac LiquidProjections (*) EventStore
  3. 3. Domain Event Store Events App RDBMS Events Projection EventsProjection Projection Projector Optimized for specific queries Separate projections database NoSQL Projector Projection- specific storage Projector HTML Raw SQL, Dapper or OR/M Run asynchronously Great for partitioning Dennis Doomen | @ddoomen | The Continuous Improver
  4. 4. Events Transaction 6 Transaction 5 Transaction 4 Transaction 3 Transaction 2 Transaction 1 Temporal Projector Read Store Time Projected until this point Immutable, thus auditable and SOX compliance Dennis Doomen | @ddoomen | The Continuous Improver
  5. 5. Domain Event Store Events App Events Projection EventsProjection Projection Projector Application projections RDBMS Reporting Projector Traditional reporting model Asynchronous OLAP Dennis Doomen | @ddoomen | The Continuous Improver
  6. 6. Dennis (v4) Persisted State Changes Dennis (v3) Role Granted PasswordChangedEvent Dennis (v4) Dennis (v3) User Created Role Granted Phone Number Added Password Changed Dennis (v5) Role Revoked Dennis (v6) Role Granted Time Dennis (v7) Password Changed Dennis Doomen | @ddoomen | The Continuous Improver
  7. 7. Event Store Projector Application Application Network Load Balancer Event Store Version 1 Version 2 events Projection ProjectorProjection bring off-line Returns HTTP 503 (Service Unavailable) Dennis Doomen | @ddoomen | The Continuous Improver Returns HTTP 503 (Service Unavailable)
  8. 8. Event Store Aggregate Root Entity Entity Value Object Aggregate Root Aggregate Root Aggregate Root Entity Value Object Value Object Dennis Doomen | @ddoomen | The Continuous Improver
  9. 9. Dennis Doomen | @ddoomen | The Continuous Improver Application Domain NoSQL / RDBMS OR/M / DAL Web UI, HTTP API, etc Lucene Index Document Projector Web UI, HTTP API, etc Web UI, HTTP API, etc Domain Commands Events Event StoreProjections Projectors Uses Event Sourcing Uses traditional CRUD architecture Indexing-based architecture Subcribe to webhooks Coarse- grained HTTP requests. Bus Subscribe Publish coarse- grained event
  10. 10. Customer #123 Correct Customer Shipping Address Command Customer Shipping Address Corrected Event Event Store Treat as a message, not a type Order #456 Correct Shipping Address Command Handler Application Customer Shipping Address Corrected Handler Order Redirected Event. Identity != natural key Identify partition key Primitive types only Avoid terms like Create, Update, Delete, Change. Avoid property change events Don’t use as inter-domain contracts Don’t expose outside the domain Dennis Doomen | @ddoomen | The Continuous Improver
  11. 11. Customer #123 Correct Customer Shipping Address Command Customer Shipping Address Corrected Event Event Store Order #456 Correct Shipping Address Command Handler Application Order Redirected Event Dennis Doomen | @ddoomen | The Continuous Improver
  12. 12. public class Order { private Status status; public void Cancel() { if (status == Status.InProgress) { Apply(new OrderCanceledEvent()); } } private void When(OrderCanceledEvent e) { status = Status.Canceled; } } In single classes Dennis Doomen | @ddoomen | The Continuous Improver
  13. 13. public partial class Order { private Status status; public void Cancel() { if (status == Status.InProgress) { Apply(new OrderCanceledEvent()); } } } In partial classes public partial class Order { private void When(OrderCanceledEvent e) { status = Status.Canceled; } } Dennis Doomen | @ddoomen | The Continuous Improver
  14. 14. public class Order { private OrderState state; public void Cancel() { if (state.Status == Status.InProgress) { state.Apply(new OrderCanceledEvent()); } } } In separate classes internal class OrderState { public Status Status { get; set; } private void When(OrderCanceledEvent e) { Status = Status.Canceled; } } Dennis Doomen | @ddoomen | The Continuous Improver
  15. 15. Risk Assessment Level Changed Risk Assessment Team Member Removed Risk Assessment Team Member Removed Risk Assessment Level Demoted Versus Dennis Doomen | @ddoomen | The Continuous Improver
  16. 16. Assembly AvSol.Domain.dll Namespace AvSol.Domain.RiskAssessments Type RiskAssessmentLevelChanged Assembly AvSol.ThreadAssessment.dll Namespace AvSol.ThreadAssessment.Risks.Domain Type RiskAssessmentLevelDowngraded Dennis Doomen | @ddoomen | The Continuous Improver
  17. 17. Command Service Some Command Handler Customer #123 Event Store Customer Created Event Get<Customer>(“123”) Customer Created Event Converter Customer Enrolled Event May split or merge events Can also run as part of migration May change the identity Unaffected Events Dennis Doomen | @ddoomen | The Continuous Improver
  18. 18. • Column constraints (e.g. data truncation) • Changes in data invariants (null vs non- null in event versions) • Unexpected projection dependencies.
  19. 19. • Causing duplicate child records • Causing large event streams • Incorrect caching strategy (e.g. on lookups) • Identity case-sensitivity • Incomplete SQL-backed event store reads.
  20. 20. Event Store Projector Projector RDBMS Subscribe Subscribe Document DB Projector RDBMS Subscribe Raw SQLNHibernate RavenDB Lookup Autonomous & independent Storage technique optimized for projection No joining of projections Avoid reusing the projections for multiple purposes Use aggressive caching during rebuilds. Caching strategy optimized for projector Owned by projector Dennis Doomen | @ddoomen | The Continuous Improver
  21. 21. Transaction Event Event Transaction Event Event Transaction Event Event RDBMS INSERT/UPDATE … WHERE … Transaction Event Event Transaction Event Event Transaction Event Event RDBMS INSERT/UPDATE … WHERE … INSERT/UPDATE … WHERE … INSERT/UPDATE … WHERE … Unit of Work Dennis Doomen | @ddoomen | The Continuous Improver
  22. 22. Document #1 Created Event Event Store Graph Projector Document #1 Closed Event (other events) Projector with active projections Archiving Projector Start archiving Document #1 Marked As Archivable Event Mark all events as archivable Tracks dependencies between documents Deletes projections related to Document #1 Can skip all archivable events during next rebuild. Dennis Doomen | @ddoomen | The Continuous Improver
  23. 23. Event Store Lucene Projector Document #1 Marked As Archivable Event Allows projectors to clean up Lucene Index Take snapshot Purge events Tombstone $tombstone stream Application Document Projector Search Tracks deleted streams for future references Stream Tombstoned Event Search Dennis Doomen | @ddoomen | The Continuous Improver
  24. 24. Dennis Doomen | @ddoomen | The Continuous Improver
  25. 25. Dennis Doomen @ddoomen Dennis Doomen | @ddoomen | The Continuous Improver
  26. 26. • The Good, The Bad and the Ugly of Event Sourcing https://www.continuousimprover.com/search/label/event%20sourcing • Effective Aggregate Design (Vaughn Vernon) http://dddcommunity.org/library/vernon_2011/ • Liquid Projections https://www.liquidprojections.net • Distributed Event Sourcing (Slides) https://www.slideshare.net/dennisdoomen/building-occasionally- connected-applications-using-event-sourcing • Data schema changes in an event sourced system (paper) https://files.movereem.nl/2017saner-eventsourcing.pdf

×