|
Posted on
2012-02-12 13:40
netfocus
阅读( 3105)
评论()
编辑
收藏
举报
- Business value of the events, the value of having a log, the fact that the Event Store is additive only.
- The biggest advantage of this architecture is that it allows you to design your model to meet specific requirements. Typically, the requirements for changing data are significantly different than those for querying data.
- Another advantage is application extensibility. In the more traditional layered architecture, services often need each other to do their job. Especially in long-running projects, the result is a big tangled mess that only the developers know how to maintain. CQRS enforces loose coupling between components through events.
- There are a few types of applications that would benefit from this architecture. However, some of the principles and ideas of CQRS would benefit any medium to large application in the end.An application that offers views on the same data is one such group. CQRS uses events to update query data. It doesn't matter if there is one table showing this data, or hundreds, each event listener component will keep its own data source up-to-date. Examples of views on information are over view pages, search engine indexes, reporting information, "what happened last month" emails, ad-hoc email notifications, etc, etc. LinkedIn is an example of such an application.Another example is applications that are likely to be extended in the future. Since events are ubiquitous in any CQRS application, it is very easy to create add-ons that act upon these events. Changes are typically a lot less intrusive than with the more traditional approach. Some web shop implementations, for example, need to start small due to budget restrictions. However, after some time, they might require an inventory feature that is updated automatically when an order is made. Perhaps some time later, a shipping department needs to be kept up-to-date about orders ready for shipping.The last type of application is the one that needs to scale. The traditional layered architecture is not one that supports scalability very well. Transaction management is a very heavy process in a scaled environment. XA transactions ask for a big price to pay on each transaction, while only one-in-many transactions actually go wrong. CQRS uses asynchronous updates through events. If any conflicting event is found (e.g. an item was bought, but the item is not in stock), we need to fix that in a compensating transaction. It is effectively the ACID vs. BASE discussion. It really is something that we (as developers) have to get used to. We have to educate ourselves, and our customers that things just go wrong from time to time. Instead of presenting the error to the user (with the default "please try again later" screen), we try to solve it in the background.
- An additional feature of CQRS that I personally like a lot is "event sourcing". In a more traditional layered architecture, audit trails are typically implemented as a side effect of the actual changes they describe. This makes an audit trail very error prone and thus unreliable. Event sourcing uses a different approach: let your event be the origin of all changes. In other words, changes will occur as a result of an event. In practice, this means that the methods on an aggregate (the term as defined by Domain Driven Design, Eric Evans) will not change its state directly. Instead, they will generate en event that is then applied on the aggregate. When the aggregate is stored in the repository, the generated events are dispatched to the rest of the application. In such case, the repository will not store the aggregate itself, but just the latest (uncommitted) events. The event stream that results is the overview of all changes that ever occurred on the aggregate. If a repository needs to rebuild an aggregate from storage, it will replay all past events. The opportunities that event sourcing provides are not limited to audit trails. You could also use these events to set the application to a certain state in time and replay events back on components for debugging purposes. Axon contains building blocks that make it easier to use event sourcing. There is an abstract implementation of an aggregate that you can extend with the case-specific business logic and a basic implementation of a repository that stores events in the file system.
- A complex domain may be easier to tackle by using CQRS.
- The other main benefit is in handling high performance applications. CQRS allows you to separate the load from reads and writes allowing you to scale each independently. If your application sees a big disparity between reads and writes this is very handy. Even without that, you can apply different optimization strategies to the two sides. An example of this is using different database access techniques for read and update.
- Firstly when one uses Event Sourcing with CQRS one can avoid the need for 2pc between the data store and the message queue that you are publishing messages to. This is because the Event Store can be used as both an event store and a queue. Conceptually the Event Store is an infinitely appending file. One can just have a read location that gets updated (chasing the end of the file) and presto you have a queue as well. A side benefit from this is that you also end up with only one disk write for both your storage and your durable queue, this may not initially seem like a big win but when you are trying to build performant systems this can help a lot!
- The second and I believe most important area where Event Sourcing really aids CQRS is in the only having a single model. If we were to say use a relational database, object database, or anything else that only keeps current state we would have a slight issue. The issue is that we have two different models that we cannot keep in sync with each other. Consider that we are publishing events to the read model/other integration points, we are also saving our current state with a tool like nhibernate. How can we rationalize that what nhibernate saved to the database is actually the same meaning as the events we published, what if they are not? When we use Event Sourcing we only use our events, they are the only model there is nothing to keep in sync. If there is a problem with the Event Stream that people use to integrate with us, like that we had a bug and never sent an event OUR state will be wrong as well.
- The largest single benefit about CQRS is when you start running into problems with the CAP theorem. You can use CQRS to get around problems you run into with CAP. The trick is that CQRS breaks up the system into multiple pieces that you can then adjust them separately. You are not avoiding CAP, you still have CAP limitations but you now have them in multiple places and you can make different choices in different places. Let’s go through such a scenario. the customer needs all three; consistency, availability, and partitionability. Doing this in a single system according to CAP is impossible. But let’s get more into the problem and apply CQRS. We now have two distinct units, the first is the write side and the second is the read side. Where is consistency needed, is it everywhere or just for certain operations? How does our application scale? What is our ratio of reads to writes? We can make different decisions on the read side and the write side. We can be ACID on the write side and BASE on the read side.
- One obvious form of return is that it's easy to serialize the events to make an Audit Log. Another use for this kind of complete Audit Log is to help with debugging. Of course, it's old hat to use log files for debugging production problems. But Event Sourcing can go further, allowing you to create a test environment and replay the events into the test environment to see exactly what happend, with the ability to stop, rewind, and replay just like you can when executing tests in a debugger. This can be particularly valuable to do parallel testing before putting an upgrade into production. You can replay the actual events in your test system and test that you get the answers you expect.
- Event Sourcing is the foundation for Parallel Models or Retroactive Events. If you want to use either of those patterns you will need to use Event Sourcing first. Indeed this goes to the extent that it's very hard to retrofit these patterns onto a system that wasn't built with Event Sourcing. Thus if you think there's a reasonable chance that the system will need these patterns later it's wise to build Event Sourcing now. This does seem to be one of those cases where it isn't wise to leave this decision to later refactoring.
- Event Sourcing also raises some possibilities for your overall architecture, particularly if you are looking for something that is very scalable. There is a fair amount of interest in 'event-driven architecture' these days. This term covers a fair range of ideas, but most of centers around systems communicating through event messages. Such systems can operate in a very loosely coupled parallel style which provides excellent horizontal scalability and resilience to systems failure.
- Event sourcing is an approach to thinking about persistent data where the primary record is a log of all events that make updates. A traditional representation of database state can be entirely recreated by reprocessing this event log. Event sourcing’s benefits include strong auditing, creation of historic state, and replaying of events for debugging and analysis. Event sourcing has been around for a while, but we think it is used much less than it should be.
- Almost-infinitely scalable; Focused on the business rather than the technology; Can grow to handle complex problems without growing development costs; Adapt to changing business requirements; Efficiently integrate with other software and systems
- Command-Query Responsibility Segregation is not a silver bullet, but rather an approach that has proven itself to be efficient in solving some of the frustrating problems of delivering enterprise software:Performance bottlenecks and scalability;Concurrency conflicts, their resolution and prevention;Data staleness;Complexity of the design, development and maintenance
- A Comprehensive Solution: When looking at how code outside the domain model interacts with it, look for the agile "simplest thing that could possibly work"—a single method call on a single object from the domain, even in the case when you're working on multiple objects. Domain events can help round out your solution for handling more complex interactions and technological integrations, without introducing any complications. When starting down this path, it took me some time to adjust my thinking, but the benefits of each pattern were quickly felt. When I began employing all of these patterns together, I found they provided a comprehensive solution to even the most demanding business domains, while keeping all the code in each part of the system small, focused, and testable—everything a developer could want.
- Performance. Because events are immutable, you can use an append-only operation when you save them. Events are also simple, standalone objects. Both these factors can lead to better performance and scalability for the system than approaches that use complex relational storage models.
- Simplification. Events are simple objects that describe what has happened in the system. By simply saving events, you are avoiding the complications associated with saving complex domain objects to a relational store; namely, the object-relational impedance mismatch.
- Audit trail. Events are immutable and store the full history of the state of the system. As such, they can provide a detailed audit trail of what has taken place within the system.
- Integration with other subsystems. Events provide a useful way of communicating with other subsystems. Your event store can publish events to notify other interested subsystems of changes to the application's state. Again, the event store provides a complete record of all the events that it published to other systems.
- Deriving additional business value from the event history. By storing events, you have the ability to determine the state of the system at any previous point in time by querying the events associated with a domain object up to that point in time. This enables you to answer historical questions from the business about the system. In addition, you cannot predict what questions the business might want to ask about the information stored in a system. If you store your events, you are not discarding information that may prove to be valuable in the future.
- Production troubleshooting. You can use the event store to troubleshoot problems in a production system by taking a copy of the production event store and replaying it in a test environment. If you know the time that an issue occurred in the production system, then you can easily replay the event stream up to that point to observe exactly what was happening.
- Fixing errors. You might discover a coding error that results in the system calculating an incorrect value. Rather than fixing the coding error and performing a risky manual adjustment on a stored item of data, you can fix the coding error and replay the event stream so that the system calculates the value correctly based on the new version of the code.
- Testing. All of the state changes in your aggregates are recorded as events. Therefore, you can test that a command had the expected effect on an aggregate by simply checking for the event.
|