1 -有人能解释一下,为什么在AKKA Persistent Actors中,更新状态是在事件被记录之后完成的?
1.1- 如果在更新状态“回调”发生之前,系统崩溃会发生什么?
- (我想我有点明白了,但我的困惑来自于我无法理解如何处理命令。我不认为它与处理事件有什么不同。见下文)*
2 -命令的执行/处理和与事件处理相关的“更新状态回调”之间是否存在差异。
2.1- -也就是说,指挥部的处理去哪里,事件的处理去哪里,这两个“处理”有必要不同吗?
我所看到的所有例子都表明,除了验证命令,然后持久化其关联事件并相应地更新Actor状态之外,处理命令没有什么特别的地方。
这意味着处理一个命令实际上就是处理一个事件。
我的困惑来自于这样一个事实,,一个事件只能记录已经发生的事情.但在所有的例子中,我已经看到,在接收到一个命令,没有什么特别的发生,如果它只是实际上,设置该动作被执行的事件(哪一个?)然后更新状态.这有点颠倒了事情的逻辑.
如果命令是create an order,那么我们可能会在验证之后自动地创建order_was_created,然后在更新状态函数之后,该函数将根据事件接收更新actor的状态。
这感觉很奇怪。所以从某种意义上说,一个命令,除了被验证,从来没有触发任何东西,特别是如果它与更新的东西,但放置一个事件,然后将触发真实的工作。
所以这里的命令只是说如果一个事件发生了,这个事件将在哪里成为现实。也就是说,它是为了恢复目的而完成的。
这是令人困惑
2条答案
按热度按时间2jcobegt1#
命令是更改数据的请求。事件是已应用的更改,并且是在事件发生后进行的更改。对数据的更改在将事件记入日志之前进行验证。已记入日志的事件被视为保证成功的更新,因为它在应用验证之后仍会保持。当持久性操作元重新合成时,它会重放所有的更改,并相应地更新状态,同时保证所有的更新都可以应用。这就是为什么状态会在之后应用的基本原因。看到被称为事件源。我认为这个presentation很好地解释了它。
v440hwme2#
Filippo De Luca最近(2016年12月)发表的文章“Akka event sourcing done right“提出了一种常用工作流的替代方案,即:
持久参与者流通常如下所示:
这个流程在第二步有一个主要的缺点。如果翻译这个命令(或刺激)的逻辑被窃听,最初的意图就会丢失。
但Filippo提供了另一个视角:
在我目前使用的应用程序中,一个持久的Actor正在响应从一堆Kafka主题中接收到的一些外部事件。这些事件在持久化它们之前被转换为本地事件。这种转换取决于当前Actor的状态,包含了很多将来可能会更改的业务规则。
这个逻辑中的一个错误使得整个事件源架构毫无意义。
我认为,一个更好的模型是在事件被持久化之后应用这个逻辑:
我的建议是完全放弃第二步,将外部命令作为事件处理,并将其存储在日志中。在这种情况下,即使我们在将命令应用于状态的代码中存在错误,我们也可以修复它,并且它将被追溯应用
然而,雷纳托·卡瓦拉坎蒂评论说
在CQRS的上下文中,域事件不是一个刺激。它只表示发生了对您的域具有某些商业价值的事情。
一个事件可以被解释并触发其他一些行为,在这种情况下,它可以被看作是一个刺激,但它不是它的第一意图。
关于Command Sourcing的想法,它是可以实现的,但它的适用性是有限的。主要原因是命令处理程序必须是纯的。必须没有副作用,没有远程调用,没有IO,什么都没有。只是对您的聚合数据进行纯函数调用。这是因为您希望重放它们并获得相同的结果。
菲利波认识到:
你说得对在我们的场景中,大多数的命令实际上是由另一个服务发送的事件。2我们存储它们,然后将更改应用到我们的模型中。3我们应用更改的方式可能会根据业务需求而变化。4但是,当然,它们不能被拒绝,而且无论如何都需要被持久化。
我同意它们不是命令,而是外部事件。
我也会说,我们可能想拒绝一个命令,而不坚持任何东西(我们确实这样做了)。