假人的CQRS和事件源

CQRS(命令和查询责任隔离)和事件源不是什么新概念。 除了NoSql,Functional Programming和Microservices之外,这些复兴概念由于能够应对现代软件挑战而受到关注。 假设您要构建的产品具有复杂的领域,并且拥有大量的用户,我可以预测,如果您遵循更传统的建筑风格,将会面临以下问题: 如何扩展以及如何处理复杂性。 大事记

CQRS的基本概念

CQRS和事件源采用一种架构样式解决了这些问题,这种架构样式不仅有效,而且不需要太多的认知工作就变得有意义。 在过去的几周中,我和一些同事参加了Greg Young在线教程中有关CQRS和Event Storming的研究小组。 该视频确实很长,因此我将重点介绍本教程中介绍的一些关键概念,但我建议您花些时间自己观看。

CQRS基于Bertrand Meyer的CQS(命令查询分离)概念。 CQS指出,每个方法都应该是执行操作的命令,或者是检索结果的查询。 不应混合考虑。 从功能的角度来看,这意味着查询方法不应有任何副作用&em;。 也就是说,它们是参照透明的,因此我们可以在没有任何上下文知识的情况下在系统的任何部分中使用它们。 这种方法有助于创建模块化且易于推理的软件。

CQRS将这一概念带入了架构层次。 我们不应该在混合了命令和查询关注的情况下创建服务。 这种方法是正交的,围绕有限的上下文创建不同的服务。 此外,任何“微服务”也应分为读写组件。 我将提供一个示例以使其易于理解。

非CQRS架构的挑战

假设我们正在建模一小部分Twitter。 用户可以鸣叫,收藏鸣叫并阅读时间线。 在非CQRS设计中,我们可以围绕名词和CRUD(创建,读取,更新和删除)动词对系统进行建模。 这些动词/动作可以表示为关系数据库中的REST(表示状态转移)接口和规范化表。 这种结构模型存在一些问题:

  • 写和读问题是混杂的,因此代码很难推理。 我们使用Hibernate之类的ORM(对象关系映射)工具来读取和写入实体,这些实体在混合时可能难以维护和理解。
  • 管理变更很困难。 认为我们是第一次创建模型是傲慢或天真的,因此我们需要一种易于更改的体系结构。
  • 对该系统的某些查询可能需要连接不同的表,这可能会在更大范围内带来问题。 规范化模型适合于优化写作场景; 您只需要在一个表中编写,而不必担心在不同的非规范化视图之间传播更改。 由于明显的原因,它们还节省了存储空间。 如今,内存已经便宜了,说实话,我过去使用过的大多数应用程序都读多于写。

进入活动世界的好处

行为建模是应对这些挑战的CQRS替代方案。 Alberto Brandolini创建了一种称为事件风暴的技术,该技术使您能够以CQRS方式对系统进行建模。 这种方法试图像人类或企业所看到的那样对系统进行建模:命令和事件流。 在我们的示例中,一个命令将是Create Tweet,而该事件始终以过去时表示为Created Tweet 。 一个命令可以生成不同的事件,并且每个事件我们可以拥有不同的使用者。 这意味着我们将来可以灵活地更改读取面,例如“ 读取时间轴 ”。

cqrs

这是一个分离写和读关注点并使用事件源的提议。 重要的是要注意,根据我们领域的约束和挑战,我们可能会稍微不同地设计此体系结构。 我们可以决定将事件队列放置在系统的开头,也可以将某些耗时的任务移至虚拟阅读器中,就像真实的Twitter在某些特殊情况下所做的那样 。 无论如何,都可以获得一些关键的好处:

  • 我们可以轻松扩展。 如今,事件队列是野兽。 Kafka在Linkedin等大型场所被用作活动存储。
  • 我们将面临最终的一致性。 此体系结构遵循即发即弃命令样式。 当我们向系统发送命令时,我们不会同步等待响应。 队列本质上是异步的,因此用户将不得不等待一段时间,直到非规范化视图得到更新。 格雷格·扬(Greg Young)认为,每个系统最终都是一致的,只是数量级的问题。 建议的解决方案正在教育用户,为什么要培训程序员。 程序员通常认为他们的系统比现实所说的更为关键。
  • 我们可以使用不同的技术来进行读写存储。 我已经建议将Kafka用作事件存储(例如,当您需要存档事件时由HDFS支持),并且可以使用Cassandra或Redis存储视图。 记住,使用这种体系结构,您无需在读取时就计算视图,因此,您不必联接表,这是一个通常的瓶颈。
  • 我们永远不需要删除或更新事件(并且不再需要'CRUD'中的'UD')。 我们不需要同步资源,因为我们的事件存储是不可变的。 如果我们不喜欢某个推文,则发送一个命令,该命令将在我们的事件存储中发布一个不喜欢的推文 。 这将触发对时间轴视图的重新计算,从而删除推文中最喜欢的操作。

但是,当您达到数百万个事件时会发生什么? 每当您在系统中收到新事件时,是否需要重播每个事件? 答案是快照。 我们将定期存储我们的视图快照并保留它们。 与该快照一起,我们将记录主题的指针(在Kafka中为偏移量),因此我们知道拍摄快照的时间。 每当我们需要重播事件以重新构成我们的视图时,我们都可以从选定的快照而不是从开始就做到。

我们为什么要重播事件? 一个重要的原因是帮助我们创建了不可复制的错误。 通常,错误会隐藏在系统状态的特定组合中,并且当系统复杂时,很难模仿。 如果用户可以发送包含命令以及导致错误的事件的报告,那么我们可以将系统重播到特定的时间点,以查明该死错误的原因。

结论

我真的相信,这种体系结构样式可以消除无法按现代需求扩展的系统的意外复杂性。 世界在变化,软件必须跟上潮流。 因此,尽管进行了大肆宣传,但事件驱动的体系结构,微服务,NoSql和函数式编程仍然存在。 它们提供了新的方法来解决软件操作和测试中的难题,从而带来潜在的结果,这对于世界各地的程序员来说都是一个激动人心的时刻。

翻译自: https://www.javacodegeeks.com/2015/07/cqrs-and-event-sourcing-for-dummies.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值