- 浏览: 40939 次
- 性别:
文章分类
最新评论
-
sunheavenvan:
我觉得不存在提炼出有所谓的本质,提炼的目的是获取较为准确的心智 ...
Jdon007四象图坐标表示 -
yangyi:
好像没有提及Seam给测试和OO设计上带来的便宜,不好意思,还 ...
Seam生命周期 -
buptwhisper:
性能一直是个问题
Seam生命周期 -
sulong:
oojdon 写道如果大家站在Gavin King的角度,包括 ...
Seam生命周期 -
may_cauc:
扬长避短吧,任何一种技术的出现都有其初衷。不要轻易否定,在否定 ...
Seam生命周期
这是axonframework的作者Allard Buijze写的文章,用CQRS来审视架构
banq也做过翻译http://www.jdon.com/jivejdon/thread/37891
Many applications use some form of persistent storage to store its state. However, important information about this state is lost: why is the state as it currently is. Furthermore, a single model is used to store information that is retrieved for many different purposes, often resulting in extremely complex and bog-slow SQL queries. Command Query Responsibility Segregation (CQRS) is an architectural style that makes a clear distinction between commands that change the application state and queries that expose the application state.
My interest in CQRS was triggered when I saw Greg Young explain “State Transitions in Domain-Driven Design” on InfoQ. In this interview, Greg explains how he sees that application would benefit from using separate models for state validation and transition on one side and maintaining a view on the current state on the other. One of the problems that Greg describes is the fact that a single model is often used for different purposes. It is nicely illustrated by the SQL query below. It shows how the model chosen in the application is not suited for the purpose of providing certain information (messages between users, in this case).
Background
queryBuilder.append(
"m.*, " +
"m.origin_participant_id as message_origin_participant_id, " +
"po.first_name as message_origin_participant_first_name, " +
"po.avatar as message_origin_participant_avatar, " +
"po_ua.username as message_origin_participant_username, " +
"CASE WHEN !isnull(po.fieldworker_project_id) THEN 'fieldworker' WHEN !isnull(po_ap.project_id) THEN 'fundraiser' ELSE 'player' END AS message_origin_participant_type, " +
"po.city as message_origin_participant_city, " +
"c.name as message_origin_participant_country, " +
"pd.first_name as message_destination_participant_first_name, " +
"pd.avatar as message_destination_participant_avatar, " +
"pd_ua.username as message_destination_participant_username, " +
"CASE WHEN !isnull(pd.fieldworker_project_id) THEN 'fieldworker' WHEN !isnull(pd_ap.project_id) THEN 'fundraiser' ELSE 'player' END AS message_destination_participant_type, " +
"m.destination_participant_id as message_destination_participant_id " +
"from internal_message m " +
"left join player po on m.origin_participant_id = po.id " +
"left join (select player_id, project_id from ambassador_project where enabled = true group by player_id) po_ap on po_ap.player_id = po.id " +
"left join user_account po_ua on po.user_account_id = po_ua.id " +
"left join country c on po.country_id = c.id " +
"left join player pd on m.destination_participant_id = pd.id " +
"left join (select player_id, project_id from ambassador_project where enabled = true group by player_id) pd_ap on pd_ap.player_id = pd.id " +
"inner join user_account pd_ua on pd.user_account_id = pd_ua.id " +
"where m.destination_participant_id = ? "
);
Wouldn’t it be a lot nice to have a query such as the one below instead?
SELECT * FROM messages WHERE receiving_participant = ?
Achieving such queries is very easy, but doing so without making your model impossible to use for maintaining state integrity and guarding invariants is a lot harder. Well, unless you apply CQRS.
Architecture
The diagram below shows an overview of a typical CQRS architecture.
When a command comes in, it will load an aggregate from the repository and execute certain operations on it. As a result of these operations, the aggregate produces events, which are picked up for storage by the repository and for dispatching by the event bus. The event bus will dispatch each event to all (interested) event handlers. Some of these event handlers will perform actions on other (related) aggregates, some others will update the database tables they manage.
Having handlers update the data in the database means that your tables do not have to be normalized anymore. Instead, CQRS allows you to optimize your tables for the way you want to query them. This makes the data layer processing your queries really simple, and maintainable.
Furthermore, since all state changes are initiated by events, these events become a reliable source for an audit trail. By storing these events, you have an audit trail that you can use to replay the entire application history. Instead of just seeing “current application state” only, you can see all the changes that have led to the current state, providing valuable information trying to find bugs or deal with customer complaints.
Benefits
Matches the natural language used
At first glance, such an architecture might look very complex and over-engineered. However, after taking the first implementation steps, it felt pretty natural. In fact, when you explain the behavior of an application, you use a style that fits CQRS quite nicely: “when an order is approved, we send a confirmation email to the customer”.
Extensibility
Imagine an order management application. With CQRS, you could have an “OrderApproved” event, which is caught by a database updating event handler as well as one that sends an email to the customer with order information. If you later on decide to store the order information in an accounting tool as well, all it takes is adding an event handler that does the accounting integration. And since you can reload historic events as well, you can even reconstruct historic information to put in the accounting table.
Reliable audit trail
As I said above [see section Architecture], the model that is used to process command will generate events. These events are the sole source of state changes for the domain classes. If you want to load an aggregate from persistent storage, it will actually load all the past events of that aggregate. This process is called Event Sourcing. When events become too numerous, you can combine a number of historic events into a single snapshot event. The events that have been combined can then be archived for auditing purposes.
Event Sourcing turns your event storage into an extremely reliable audit trail. The events do no only show what happened and when, but they will also reveal the intention a user had. Not only is it an audit trail that will never move out-of-sync with your application, you can use the audit trail to actually replay all actions in the application. Events are not just a notification of state change, they are also the source of state change.
Transparent distributed processing
When using events as the trigger for state changes, you can easily distribute your application over multiple processing units (servers, JVM’s, whatever). Events can easily be serialized and sent from one server to another over JMS, via the file system or even email. The Spring Integration framework –a messaging framework – fits nicely with the event processing concept.
You could even let certain types of aggregates live on dedicated machines. This allows you to choose different SLA’s for different parts of you application, such as giving order creation a higher priority than sales reporting.
Performance and Scalability
Since event handling is done asynchronously, a user does not have to wait for all changes to be applied. Especially when integrating with external systems, this can improve liveness of an application significantly.
Another aspect of CQRS is that it heavily builds upon BASE (Basic Availability, Soft-state, Eventual consistency) transactions. Although the “eventual” part scares a lot of customers and developers, the price of distributed ACID transactions is one that customer typically resent. In most cases “eventual” is just a matter of several milliseconds. But you’re free to make that seconds, minutes or even hours if your SLA permits it (think of management reports that are only read once a week or month).
Asynchronous analysis
When you build a CQRS style application, all activity in your application is processed using events. This makes it easy to catch these events and monitor them for inconsistent behavior. Event analysis tools like Esper allow you to monitor event streams for patterns that indicate possible fraud.
For example, when you detect that a sudden large number of users has an increased amount of failed login attempts, you could decide to block these accounts for a small period of time. In one of our projects, we use RSA Adaptive Authentication to increase the level of authentication required when someone tries to login on an account that might be the subject of dictionary attacks.
发表评论
-
论继承
2011-09-05 17:37 218继承是现实系统中非常 ... -
Jdon007四象图坐标表示
2011-09-03 11:42 1637http://www.jdon.com/jivejdon/th ... -
面向对象掠影
2011-07-16 22:25 838转自链接:http://www.cnblo ... -
specification 规格模式
2011-02-14 22:57 115MF 和 Evans 发明的模式 -
A comparison of DCI and SOA, in Java_003
2011-02-14 12:43 62DCI和SOA的对照 -
DCI architecture - The Common Sense of Object Orientated Programming
2011-02-14 12:38 77In regular OO, I work with cla ... -
MVC To DCI
2011-02-14 12:29 204MVC to DCI -
DCI in Real World
2011-02-14 12:22 834逃出面向类编程的魔爪,重新思考对象 This is a ... -
DCI之转账简单Example
2011-02-14 11:33 194http://stackoverflow.com/questi ... -
The DCI Architecture
2011-02-14 01:05 1172The DCI Architecture: A ... -
为关系数据库设计对象
2011-02-12 20:36 967这是DDD的原文,我认为最好的结论就是最后加粗 ... -
DDD 概念
2011-02-11 15:22 786来自一个PPT的截图 ... -
UML元素
2011-02-11 14:52 669UML 统一建模语言,它是表达我们OO建模的图形工具,UML图 ... -
DCI and Services (EJB)
2011-02-10 22:38 783http://blog.maxant.co.uk/peb ... -
来自Jdon的DDD总结
2011-02-10 22:31 938http://www.jdon.com/jivejdon/th ... -
DDD设计,为什么我热爱CQRS
2011-02-10 22:25 1502地址是:http://jonathan-oliver.bl ... -
设计模式的脉络
2011-02-10 14:13 734设计模式一般是指GOF那本书引出来的名词,其应该是代码模式,而 ... -
对象设计原则
2011-02-08 00:36 719现在我们面对的是让人 ...
相关推荐
在当前的数字化时代,数据隐私保护与机器学习模型的协同训练成为了亟待解决的问题,而联邦学习(Federated Learning, FL)正是为应对这一挑战而提出的新兴研究领域。联邦学习允许不同机构间的模型协作训练,同时保持...
本文献《Rethinking the Inception Architecture for Computer Vision》由Google的研究人员撰写,主要探讨了如何优化和扩展卷积神经网络(CNN),特别是在计算效率和模型参数数量方面进行改进。自2012年Krizhevsky等...
《统计思维:贝叶斯统计课程及R和Stan示例》是一本专注于贝叶斯统计思想的教材,本书以R语言和Stan软件为工具,介绍统计建模的基本原理和方法。本书的作者是Richard McElreath,他在书中融入了可读性强的解释、...
复杂数据库高可用性架构设计与RDMA网络 在分布式数据库系统中,高可用性是至关重要的一点,它可以确保系统在机器故障或网络中断的情况下继续提供服务。为了达到高可用性,数据库系统通常采取数据复制的方法,即将...
优质文献资料分享,希望可以帮助到你~
根据所提供的文件内容,我们可以提炼出关于“Rethinking”包的知识点,该包是专门用于处理贝叶斯分析的技术文档。以下是详细的说明: 首先,“Rethinking”包是专门为贝叶斯统计分析设计的R语言包,它起源于一个...
这篇论文“Rethinking Graph Transformers with Spectral Attention”提出了光谱注意力网络(Spectral Attention Network, SAN),它利用学习到的位置编码(Learned Positional Encoding, LPE)来利用拉普拉斯矩阵的...
使用Brms,ggplot2和tidyverse重新进行统计思考:第二版 欢迎我的 的姊妹项目。 我们的目标是翻译McElreath 的代码,使其适合和框架。 当前的0.1.1版本包含所有17章的初稿,这些初稿已编在一起成为一本Bookdown...
《重新思考文本分段:Rethinking Text Segmentation数据集2详解》 在自然语言处理领域,文本分段是一项至关重要的任务,它涉及到对文本进行有效的切割和组织,以便更好地理解和分析文本内容。Rethinking Text ...
Statistical Rethinking A Mostly Bayesian Course in Mostly Non-Bayesian Statistics Richard McElreath 很好的入门资料,学习stan和R不错
这个是行人属性识别框架Rethinking_of_PAR,里面包含了PA100k数据集还有自己训练的PA100K的模型,模型格式为pt格式,此外还有demo.py直接对图片进行推理预测,官方没有提供预训练模型也没有提供对图片预测脚本,这个...
总之,“Rethinking the Heatmap Regression for Bottom-Up Human Pose Estimation”这篇论文重新审视了自下而上人体姿态估计中的热图回归问题,提出了尺度自适应和权重自适应的策略,有效解决了不同人体尺度和标注...
这篇文章《2020-Rethinking Pre-training and Self-training.pdf》针对这两种方法进行了重新思考,并提出了新的见解和实验结果。 首先,我们需要理解预训练的概念。预训练指的是在一个大型和多样化的数据集上训练...
这项工作的代码可以在GitHub上的开源项目(https://github.com/osiriszjq/Rethinking-positional-encoding)中找到,便于研究者进一步探索和验证。 位置编码在现代语言模型和涉及信号编码为神经网络权重的视觉任务...
使用Brms,ggplot2和tidyverse重新进行统计 我喜欢McElreath的。 然而,我来用Bürkner的偏爱做贝叶斯回归的R.当。 我还更喜欢使用Wickham的绘图,并使用样式的语法(您可能会在或学到)。 因此,该项目试图重新表达...
Rethinking the design of the Internet:The end to end arguments vs. the brave new world 作者:Marjory S. Blumenthal, Computer Science & Telecommunications Bd David D. Clark, M.I.T. Lab for Computer ...