事件溯源与事件驱动架构的区别

mub*_*bir 13 event-driven cqrs event-sourcing saga apache-kafka

我正在研究事件基础架构,并了解了两种架构事件溯源和事件驱动架构。

我的理解如下

事件驱动 :

  • 用于分布式事务,如 saga
  • 事件被推送到消息队列,监听器监听并执行相应操作。

事件溯源:

  • 习惯了像 CQRS 这样的模式。
  • 负责保存数据或同步数据库的事件

但我不明白的是,为什么在事件源中重播事件会导出整个事务,但在事件驱动中是不可能的。

如果有人用现实生活中的例子来描述它将会很有帮助。

Lev*_*sey 34

事件驱动架构是关于通过发布事件进行通信的组件,而不是相互进行(例如)RPC 调用或操纵共享状态。这是一种通信策略(尽管该策略通常依赖于消息持续相当长的时间)。

事件溯源是指组件本身将它们所保存的事件历史视为其状态(或至少是它们实际关心的状态)的最终真相来源。这是一种持久性策略,本质上并没有涉及任何有关沟通的内容。事件溯源本质上与 CQRS 没有任何关系(尽管事件溯源系统经常发现 CQRS 是一种有用的方法,允许查询必须重播事件的重要子集才能使用针对该用途更优化的数据模型情况;同样,使用事件源持久性模型来处理 CQRS 中的命令也有一些优点)。

持久事件是最终事实来源意味着事件重播可以恢复状态(根据定义,如果事件重放无法恢复状态,则事件不是最终事实来源)。

事件溯源会保留日志供您自己使用,这样您就不会忘记。事件驱动架构是关于传达他人发生的事情。通常,EDA 中的组件无法从已发布的事件中恢复其全部状态,因为并非所有更改其状态的内容都值得发布。只接受其他组件发布的输入事件的组件能够根据重播这些事件来恢复其状态(尽管在许多情况下,按照发布的顺序重播它们是相当困难的......),尽管我会认为这是命令源,而不是事件源,因为一个组件发布的事件在被另一个组件使用时是一个命令(该命令是“尝试将此事件合并到您的世界视图中”)。

事件源组件中的事件日志是派生事件以在事件驱动架构中发布的非常好的(我什至建议它是最佳的)源,因此事件源组件可以成为事件驱动架构的一部分。

例如,考虑由关系数据库支持的购物车服务。购物车在数据库中由表中的一行表示cartscartitems表中的轨道表示“购物车 ABC 中有 2 个 USB 充电器,每个充电器价格为 4.75 美元”。为了将商品添加到购物车,我们在表中插入(或更新,如果只是数量变化)行cartitems。签出购物车后,我们会发布购物车及其内容的 JSON 表示形式,以便运输服务拥有购物车中的内容并设置carts.checked_outTRUE

这是一个完全OK的事件驱动架构。购物车服务向运输服务传达有已签出的购物车的信息。它不是事件源的:我们无法从事件重建数据库。

购物车服务可以是事件源的。它将事件存储在事件存储中(事件存储可以是为事件源的需要而设计的数据存储,也可以是以特定方式使用的关系数据库或非关系数据库(例如表events))。购物车 ABC 的以下事件序列可能会写入事件存储:

  1. AddItem {“USB 充电器”,$4.95 }
  2. AddItem {“USB 充电器”,$4.95 }
  3. AddItem {“骆驼书”,$34.95 }
  4. 删除项目{“骆驼书”}
  5. DiscountApplied { 要求 { 2, "USB 充电器" }, -$0.40 }
  6. AddItem {“C 编程语言”,$19.95 }
  7. CheckedOut { Items { Item { "USB 充电器", 2, $4.75 }, Item { "C 编程语言", 1, $19.95 } } }

最后一个事件(以及它用于购物车 ABC 的事实,即与该事件关联的元数据)可用于派生要发布的事件。需要注意的一件关键事情是,除了这些事件之外,没有任何其他内容被写入数据库。

就事件驱动架构而言,这两个购物车服务基本相同:它们发布相同的结帐事件。事件源实际上只是该服务的实现细节。