Sunday 3 May 2015

Event Sourcing and CQRS

1. Event Sourcing

Use an append-only store to record the full series of events that describe actions taken on data in a domain, rather than storing just the current state, so that the store can be used to materialize the domain objects. This pattern can simplify tasks in complex domains by avoiding the requirement to synchronize the data model and the business domain; improve performance, scalability, and responsiveness; provide consistency for trans- actional data; and maintain full audit trails and history that may enable compensating actions.

There is no contention during the execution of transactions, can vastly improve performance and scalability for applications, especially for the presentation level or user interface. Events do not directly update a data store; they are simply recorded for handling at the appropriate time.

Event sourcing can help to prevent concurrent updates from causing conflicts because it avoids the requirement to directly update objects in the data store. However, the domain model must still be de- signed to protect itself from requests that might result in an inconsistent state.


Issues and Consideration
  • The system will only be eventually consistent when creating materialized views or generating projections of data by replaying events. There is some delay between an application adding events to the event store as the result of handling a request, the events being published, and consumers of the events handling them. During this period, new events that describe further changes to entities may have arrived at the event store.
  • The event store is the immutable source of information, and so the event data should never be updated. The only way to update an entity in order to undo a change is to add a compensating event to the event store, much as you would use a negative transaction in accounting. The current state of an entity can be determined only by replaying all of the events that relate to it against the original state of that entity.
  • Even though event sourcing minimizes the chance of conflicting updates to the data, the application must still be able to deal with inconsistencies that may arise through eventual consistency and the lack of transactions.
  • When you want to record events that occur, and be able to replay them to restore the state of a system; use them to roll back changes to a system; or simply as a history and audit log.  


This pattern might not be suitable in the following situations:
  • Small or simple domains, systems that have little or no business logic, or non-domain systems that naturally work well with traditional CRUD data management mechanisms.
  • Systems where consistency and real-time updates to the views of the data are required.
  • Systems where audit trails, history, and capabilities to roll back and replay actions are not required.
  • Systems where there is only a very low occurrence of conflicting updates to the underlying data. For example, systems that predominantly add data rather than updating it.


2. CQRS

Command and Query Responsibility Segregation (CQRS) is a pattern that segregates the operations that read data (Queries) from the operations that update data (Commands) by using separate interfaces. This implies that the data models used for querying and updates are different. The models can then be isolated.


This pattern can maximize performance, scalability, and security; support evolution of the system over time through higher flexibility; and prevent update commands from causing merge conflicts at the domain level. 


Issues and Consideration
  • Dividing the data store into separate physical stores for read and write operations can increase the performance and security of a system, but it can add considerable complexity in terms of resiliency and eventual consistency. The read model store must be updated to reflect changes to the write model store, and it may be difficult to detect when a user has issued a request based on stale read data— meaning that the operation cannot be completed. 
  • A typical approach to embracing eventual consistency is to use event sourcing in conjunction with CQRS so that the write model is an append-only stream of events driven by execution of commands. These events are used to update materialized views that act as the read model.  
 When to Use this Pattern:

  • Collaborative domains where multiple operations are performed in parallel on the same data. CQRS allows you to define commands with a sufficient granularity to minimize merge conflicts at the domain level.
  • Use with task-based user interfaces (where users are guided through a complex process as a series of steps), with complex domain models, and for teams already familiar with domain-driven design (DDD) techniques. The write model has a full command-processing stack with business logic, input validation, and business validation to ensure that everything is always consistent for each of the aggregates (each cluster of associated objects that are treated as a unit for the purpose of data changes) in the write model. The read model has no business logic or validation stack and just returns a DTO for use in a view model. The read model is eventually consistent with the write model. 

  • Scenarios where performance of data reads must be fine-tuned separately from performance of data writes, especially when the read/write ratio is very high, and when horizontal scaling is required. For example, in many systems the number of read operations is orders of magnitude greater that the num- ber of write operations. To accommodate this, consider scaling out the read model, but running the write model on only one or a few instances. A small number of write model instances also helps to minimize the occurrence of merge conflicts.
  • Scenarios where one team of developers can focus on the complex domain model that is part of the write model, and another less experienced team can focus on the read model and the user interfaces.
  • Scenarios where the system is expected to evolve over time and may contain multiple versions of the model, or where business rules change regularly.
  • Integration with other systems, especially in combination with EventSourcing, where the temporal failure of one subsystem should not affect the availability of the others. 
This pattern might not be suitable in the following situations:
  • Where the domain or the business rules are simple.
  • Where a simple CRUD-style user interface and the related data access operations are sufficient.
  • For implementation across the whole system. There are specific components of an overall data man- agement scenario where CQRS can be useful, but it can add considerable and often unnecessary com- plexity where it is not actually required. 

3. Use Event Sourcing with CQRS

The CQRS pattern is often used in conjunction with the Event Sourcing pattern. CQRS-based systems use separate read and write data models, each tailored to relevant tasks and often located in physically separate stores. When used with Event Sourcing, the store of events is the write model, and this is the authoritative source of information. The read model of a CQRS-based system provides materialized views of the data, typically as highly denormalized views. These views are tailored to the interfaces and display requirements of the application, which helps to maximize both display and query performance. 

When using CQRS combined with the Event Sourcing pattern, consider the following:
  • As with any system where the write and read stores are separate, systems based on this pattern are only eventually consistent. There will be some delay between the event being generated and the data store that holds the results of operations initiated by these events being updated.
  • The pattern introduces additional complexity because code must be created to initiate and handle events, and assemble or update the appropriate views or objects required by queries or a read model. The inherent complexity of the CQRS pattern when used in conjunction with Event Sourcing can make a successful implementation more difficult, and requires relearning of some concepts and a dif- ferent approach to designing systems. However, Event Sourcing can make it easier to model the do- main, and makes it easier to rebuild views or create new ones because the intent of the changes in the data is preserved.
  • Generating materialized views for use in the read model or projections of the data by replaying and handling the events for specific entities or collections of entities may require considerable processing time and resource usage, especially if it requires summation or analysis of values over long time periods, because all the associated events may need to be examined. This may be partially resolved by imple- menting snapshots of the data at scheduled intervals, such as a total count of the number of a specific action that have occurred, or the current state of an entity. 

Reference:
CQRS



Boldradius CQRS example

CRDT

Patterns of Enterprise Application Architecture


No comments:

Post a Comment