我正在处理用于管理银行信用卡的应用程序。该应用程序选择了 CQRS 和事件溯源架构。应用程序中最重要的聚合是CreditCard控制信用卡生命周期。它看起来像:
class CreditCard {
private int status;
public void activate() {...}
public void deactivate () {...}
...
}
Run Code Online (Sandbox Code Playgroud)
如果方法调用成功,它的activate和deactivate方法分别保护信用卡不变量和发布CardActivatedEvent和CardDeactivatedEvent。我们将这些事件存储在事件存储中,以便稍后在命令端进行聚合重建。我们将这些事件应用于各种视图。我们使用这些事件通知其他第三方系统。目前一切都很好。
最近,我们收到了一项新要求,即按月向所有有效信用卡收费。
我的第一直觉是,好吧,我们可以将charge方法添加到同一个CreditCard聚合中。该方法可以检查一些与充电相关的不变量。例如,卡是否处于正确的收费状态,是否已经收费等。成功调用后,此方法可以发布CardChargedEvent。然后我们可以创建一些流程管理器,它会每月查询一次活动信用卡的视图端以获取它们的 ID。有了这些 ID,流程管理器可以向命令端发出多个收费命令(每个信用卡聚合一个)。对于收到的每个充电命令,命令端将重建CreditCard聚合对象并调用它charge方法。唯一的问题是这种方法看起来效率很低。特别是关于命令端的数据库往返(每个聚合实例一次读取和一次写入)。如果我们考虑到我们可以轻松地在我们的应用程序中拥有 10 万多张信用卡的等式,这个往返开销开始在我看来有点问题。
有没有人对 CQRS/ES 系统上的批处理操作有任何经验?我的担心有效吗?遇到这种情况怎么办?您如何在 CQRS 系统中实现批处理?
我想到的另一种选择是,对于收费用例,我放弃了 CQRS/ES/DDD 原则,并在我们的一个视图数据库上使用存储过程来实现整个过程。这个过程可以在信用卡视图表中搜索合适的信用卡,并用找到的记录填充“待收费队列”表。然后我可以有一些外部进程读取第二个表并执行它需要做的任何事情。