CQRS架构学习笔记

  1. CQRS is just a concept that we can seperate the application to two parts: the write part and the read part, that's all;
  2. Command: A command represents what user want to do, user can send a command to the system to ask the system what he or she wants to do; command doesn't have result. The client can make of the query data store when validating commands. On the server side, the only reason that such a command would fail would be due to concurrency. As such, validation can be performed on the client, checking that all fields required for that command are there, number and date ranges are OK, that kind of thing. The server would still validate all commands that arrive, not trusting clients to do the validation. What we see is that in this model, commands don’t need to be processed immediately – they can be queued. Another part is the issue of failed message processing due to the database being down or hitting a deadlock. There is no reason that such errors should be returned to the client – we can just rollback and try again. When an administrator brings the database back up, all the message waiting in the queue will then be processed successfully and our users receive confirmation. The system as a whole is quite a bit more robust to any error conditions. Thinking through the order in which commands and events are processed can lead to notification patterns which make returning errors unnecessary. Messaging guarantees that the command will get it's chance to be processed even if the database is deadlocked or even the entire server is down.
  3. Command Handlers:The handlers of the command, one command only has one command handler; we’re not returning errors to the client (who is already sending us valid commands), maybe all we need to do on the client when sending a command is to tell the user “thank you, you will receive confirmation via email shortly”. We don’t even need the UI widget showing pending commands. Command handlers are responsible for:Performing any required validation on the command.Invoking the domain — coordinating objects in the domain, and invoking the appropriate behaviour on them.Command handlers are application services, and each execution represents a separate unit of work (e.g. a database transaction). There is only one command handler per command, because commands can only be handled once — they are not broadcast out to all interested listeners like event handlers.
  4. Command Service:Dispatch the command to a corresponding command handler.
  5. Domain: The DDD domain model, seperated by the aggregates, represents the domain structure and business logic; There is nothing that states that all commands must be processed by the same domain model. Arguably, you could have some commands be processed by transaction script, others using table module (AKA active record), as well as those using the domain model. Event-sourcing is another possible implementation. Another thing to understand about the domain model is that it now isn’t used to serve queries. So the question is, why do you need to have so many relationships between entities in your domain model? Do we really need a collection of orders on the customer entity? In what command would we need to navigate that collection? In fact, what kind of command would need any one-to-many relationship? And if that’s the case for one-to-many, many-to-many would definitely be out as well. I mean, most commands only contain one or two IDs in them anyway. Any aggregate operations that may have been calculated by looping over child entities could be pre-calculated and stored as properties on the parent entity. Following this process across all the entities in our domain would result in isolated entities needing nothing more than a couple of properties for the IDs of their related entities – “children” holding the parent ID, like in databases. In this form, commands could be entirely processed by a single entity – viola, an aggregate root that is a consistency boundary.
  6. Aggregate: A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the Aggregate, designated as the root. A set of consistency rules applies within the Aggregate's boundaries. Problem: It is difficult to guarantee the consistency of changes to objects in a model with complex associations. Invariants need to be maintained that apply to closely related groups of objects, not just discrete objects. Yet cautious locking schemes cause multiple users to interfere pointlessly with each other and make a system unusable. [DDD, p. 126] Solution: Cluster the Entities and Value Objects into Aggregates and define boundaries around each. Choose one Entity to be the root of each Aggregate, and control all access to the objects inside the boundary through the root. Allow external objects to hold references to root only. Transient references to the internal members can be passed out for use within a single operation only. Because the root controls access, it cannot be blindsided by changes to the internals. This arrangemens makes it practical to enforce all invariants for objects in the Aggregate and for the Aggregate as a whole in any state change. The whole point of an aggregate and its aggregate root is to define an aggregate boundary. This boundary states that inside things should be consistent hence invariants should be satisfied. But it also means that outside, you cannot enforce invariants. If you need to enforce invariants outside an aggregate, it means, it's not a proper aggregate.
  7. Domain Event:Represents what happened of the aggregates;
  8. Event Sourcing:Domain events can be used to rebuild the aggregate by replaying them of all;
  9. Event Bus:A bus to publish domain event, there are synchronous event bus, asynchronous event bus, and composite event bus;
  10. Repository:Act as an in-memory collection which contains all the aggregates;
  11. Event Store: Stores all the persisted domain events;
  12. Is suited to complex domains, commonly applied along with DDD;
  13. Separate the write and read model;
  14. Use message to synchronize the write and read model, domain event is a type of message;
  15. Task-based UI design; A core element of CQRS is rethinking the design of the user interface to enable us to capture our users’ intent; A task based UI is quite different from a CRUD based UI. In a task based UI you track what the user is doing and you push forward commands representing the intent of the user. I would like to state once and for all that CQRS does not require a task based UI. We could apply CQRS to a CRUD based interface (though things like creating separated data models would be much harder). There is however one thing that does really require a task based UI… That is Domain Driven Design. The Application Service Layer in Domain Driven Design represents the tasks the system can perform. It does not just copy data to domain objects and save them… It should be dealing with behaviors on the objects… Before going further let’s look at what happened if we did; there would be no verbs in our ubiquitous language except for “Create”, “Delete”, and “Change”. While there exist many domains where this is what the Ubiquitous Language is actually like, you probably should not be using Domain Driven Design for such systems.
  16. One command effect one aggregate;
  17. Aggregate defines the transactional consistency boundary; Inside the aggregate, consistency is guaranteed. Outside... it's not. So generally you should not have operations that spans several aggregates and have to be consistent. If you need a transaction that spans two aggregates, you should first review your aggregate boundaries.
  18. Should know the distinction between: message, command, event;
  19. Events are not about "field x changed", but about some change happening in real world with it's context and meaning, expressed in the language that makes sense to involved parties.
  20. Event Sourcing should be used; Event sourcing capture all changes to an application state as a sequence of events. We can query an application's state to find out the current state of the world, and this answers many questions. However there are times when we don't just want to see where we are, we also want to know how we got there. Event Sourcing ensures that all changes to application state are stored as a sequence of events. Not just can we query these events, we can also use the event log to reconstruct past states, and as a foundation to automatically adjust the state to cope with retroactive changes.
  21. Use the eventual consistency to increase your saclability and availability, not transactional consistency;
  22. We always use unit of work to tracking and store all the happened domain events;
  23. There is no assurance of order between event handlers;
  24. The inter-aggregate communication is a business process, and the best way to implement the business process (specially the long-running process transactions) is saga;
  25. Aggregates receive commands and publish events, and sagas receive events and dispatch commands;
  26. If there is a situation where more than a single AR was involved, that indicates that there was some sort of business process (as compared to business logic) will occur.
  27. How to persist the saga status? Also use the event sourcing, called state-change-sourced saga with a full history of state changes;
  28. Rules to design aggregates: 1) model true invariants; 2)design small aggregates; 3) reference other aggregates by id; 4) Use eventual consistency between aggregates(after asking whose job it is);
  29. In CQRS, the command handler is doing the same thing as the application service in Eric's DDD;
  30. Command does not have return value, and we must ensure the command is valid before it is sent to server; When the command is processing asynchronously, we might show user information like "Your request is being processing, please wait for a few seconds.". As soon as the command is succeed (or failed), user is automatically taken to the next screen. This is trivial to do with AJAX in web UI. Desktop UIs are even simpler.
  31. In some cases, use SendAndBlock pattern to communicate between web client and server; One thing to notice in the SendAndBlock is that the web page renders synchronously from the user's perspective, the interaction is synchronous and blocking, even though behind the scenes NServiceBus is doing asynchronous messaging.
  32. There are two main integration points in Ncqrs-NServiceBus tandem. First one is transporting commands and the second one is publishing events;
  33. There is not need the domain service(builder block in Eric's DDD) again, replaced by event and saga;
  34. You should never delete an aggregate. You should mark it is out of date or unavailable. Deciding what to do with the remaining references is a business decision;
  35. There are two kinds of logic: 1) Processing domain logic; 2) Processing selection logic; Processing domain logic is the business logic that manipulates the application. Processing selection logic is the logic that chooses which chunk of processing domain logic should run depending on the incoming event. You can combine these together, essentially this is the Transaction Scriptapproach, but you can also separate them by putting the processing selection logic in the event processing system, and it calls a method in the domain model that contains the processing domain logic;
  36. About the validation in CQRS: 1) do validation at the client before the command is send to server; 2) In the command handler, also do the validation as the client does; 3) In the command handler, do the process logic validation, such as the uniqueness check; 4) Put the business logic validation inside the aggregate; 5) In some cases, you could encounter a concurrency violation that cannot be detected until the aggregate root is touched. We just throw exception when this occur and there won't generate dirty data as we do all the data changes in the unit of work and all updates are in a transaction, if any exception occur the transaction will be rollback.
  37. Current State Backing: Pros : 1) Easier to retrofit on a legacy project; 2)Well known technology/tools/skill sets; 3)Easier sell for an organization. Cons: 1) Dual models cost more and contain risk; 2) Non-Event Centric. Event Storage Backing: Pros: 1) Single Event Centric Model; 2) Simplified/Better Testing; 3) Conflict Management. Cons: 1) Harder to sell to an organization; 2) Less known tools/technologies (though you can implement the Event Store in a RDBMS which kind of mitigates this); 3) Very difficult to migrate a legacy app to.
  38. In most systems, the number of reads (queries) is typically an order of magnitude higher than than the number of writes (commands) — particularly on the web. It is therefore useful to be able to scale each side independently.
  39. When we say "CQRS" architecture, this often means: "CQRS Principle" + "Message-driven architecture" + "Domain-Driven Design" + "Event Sourcing", we also called this DDDD(Distributed Domain-Driven Design) .
  40. What is a saga in contrast to a process manager? The intent of these patterns is different. A process manager is a workflow pattern which can, as you say, be built on top of a state machine. A process manager will retain state between messages, and will contain logic in order to determine which action should be taken in response to a message (for example, transitioning state or sending another message). Some frameworks incorrectly refer to these as sagas.By contrast, a saga (according to the original definitions) is a pattern intended to help manage failures. It involves multiple workflows across systems, where each will allow some form of compensating action to be taken in a later transaction in the case of a failure elsewhere.This compensation is the defining characteristic of a saga. Note that the saga itself does't know what the compensating action might be. Sagas are often implemented using the routing slip pattern. A system participating in a saga might use a process manager to actually handle its piece of processing.
时间: 2024-12-22 01:06:29

CQRS架构学习笔记的相关文章

架构学习笔记

.系统之间耦合:用异步处理代替同步处理 针对系统异常,提供降级处理,提供有限的合格服务.前端页面系统,php, 使用优化器来优化php代码.   将系统进行分级,按照重要性: 一级系统:因为是强依赖关系,所以要同步调用,重试机制. 二级系统,异步调用. 系统拆分后,单独改造系统,优化系统容易.相互隔离,调试和排错方便. 大系统做小,小系统做大(精通). 服务soa化:高内聚,低耦合.零售型电商的主流办法.拥有更好的伸缩性和扩展性.拆分让系统性能瓶颈更容易定位. 如何降级处理,我没接触过.只是有这

API Demos 2.3 学习笔记 (3)-- Android应用程序架构

更多精彩内容,请点击阅读:<API Demos 2.3 学习笔记> Android应用程序以可以分为下三种类型:1.前端Activity(Foreground Activities):通俗一点讲Activity可以理解为一个界面容器,里面装着各种各样的UI组件.例如,上面例子中"Hello World" 显示界面.2.后台服务(Background Services):系统服务(System Service).系统Broadcast(广播信息)与Receiver(广播信息)

谈一下关于CQRS架构如何实现高性能

CQRS架构简介 前不久,看到博客园一位园友写了一篇文章,其中的观点是,要想高性能,需要尽量:避开网络开销(IO),避开海量数据,避开资源争夺.对于这3点,我觉得很有道理.所以也想谈一下,CQRS架构下是如何实现高性能的. 关于CQRS(Command Query Responsibility Segration)架构,大家应该不会陌生了.简单的说,就是一个系统,从架构上把它拆分为两部分:命令处理(写请求)+查询处理(读请求).然后读写两边可以用不同的架构实现,以实现CQ两端(即Command

VC文件过滤系统驱动开发Filemon学习笔记

WINDOWS文件过滤系统驱动开发,可用于硬盘还原,防病毒,文件安全防护,文件加密 等诸多领域.而掌握核心层的理论及实践,对于成为一名优秀的开发人员不可或缺. WINDOWS文件过滤系统驱动开发的两个经典例子,Filemon与SFilter,初学者在经 过一定的理论积累后,对此两个例子代码的研究分析,会是步入驱动开发殿堂的重要一步 ,相信一定的理论积累以及贯穿剖析理解此两个例程后,就有能力开始进行文件过滤系统 驱动开发的实际工作了. 对于SFilter例子的讲解,楚狂人的教程已经比较流行, 而F

Hadoop学习笔记一 简要介绍

这里先大致介绍一下Hadoop. 本文大部分内容都是从官网Hadoop上来的.其中有一篇介绍HDFS的pdf文档,里面对Hadoop介绍的比较全面了.我的这一个系列的Hadoop学习笔记也是从这里一步一步进行下来的,同时又参考了网上的很多文章,对学习Hadoop中遇到的问题进行了归纳总结. 言归正传,先说一下Hadoop的来龙去脉.谈到Hadoop就不得不提到Lucene和Nutch.首先,Lucene并不是一个应用程序,而是提供了一个纯Java的高性能全文索引引擎工具包,它可以方便的嵌入到各种

图解HTTP学习笔记——简单的HTTP协议

简单的HTTP协议 前言 最近在学习Web开发的相关知识,发现<图解HTTP>这本书通俗易懂.所以花时间学习这本书,并记录下学习笔记. 如上图,我们每天都在浏览网页,一般我们都是在浏览器地址栏输入要访问的网站的地址(如百度),按下回车,浏览器就显示了我们要访问的网站的网页. 那么在我们敲下回车键的那一刻,究竟发生了什么呢.通过今天的学习,能大致了解其中原理,并简单学习HTTP协议. 目录 1.客户端与服务器端2.HTTP是不保存状态的协议3.请求URI定位资源4.告知服务器意图的HTTP方法5

kali linux web渗透测试学习笔记

    kali linux web渗透测试学习笔记 metasploit使用方法: 启动: 第一步:启用Postgresql服务.service postgresql start 第二步:启用metasploit服务.service matasploit start 第三步:启动框架.msfconsole 一个ASP站点的sql注入 测试数字型注入点 1.网址:asp?ID+13,后面加',看看是什么数据库,然后输入1=1,1=2,得到数据库是microsoft acess 2.转用sqlma

Django学习笔记

1. 学习历程 从学了Python以来,我都一直想着用它来做点什么.从开始用python来写简单的工具脚本,然后再是网络信息抓取程序. 听说可以用Python来做网站,所以我了解了一下web.py与Django.第一次接触Django,由于没有网络方面的基础,所以没弄两下就放弃了. 后来,我研究了一下Python自来的SimpleHTTPServer,然后读懂了CGIHTTPServer,才对Web的实质有了了解. 在这个基础上,我再次重拾Django.这次,终于学会了. 原来它是那么的美妙!

简单入门——深度学习笔记(Part I)

更多深度文章,请关注:https://yq.aliyun.com/cloud 作者介绍:Deepak Shah Deepak Shah毕业于德克萨斯奥斯汀分校,徒步旅行爱好者,目前是深度学习\数据科学实习生,研究领域专注于深度学习.编程.金融等方面. 个人主页:http://www.deepakvshah.com/ Medium论坛:https://medium.com/@dvshah13 Github论坛:https://github.com/Dvshah13  笔记分为两个部分,本文是笔记P