我正在使用Cassandra和Kafka进行事件来源,并且效果很好。但是我最近才发现设计/设置中潜在的重大缺陷。简介:
聚合命令处理程序基本上是kafka使用者,它消耗有关主题的感兴趣消息:
1.1收到命令时,它将加载聚合的所有事件,并为每个事件重播聚合事件处理程序,以使聚合恢复到当前状态。
1.2根据命令和总线逻辑,然后将一个或多个事件应用于事件存储。这涉及将新事件插入cassandra中的事件存储表。这些事件会使用汇总的版本号标记-从新汇总的版本0开始,从而可以进行预测。此外,它将事件发送到另一个主题(出于投影目的)。
1.3这些事件发布后,kafka消费者将收听该主题。该消费者将充当投影仪。当它收到感兴趣的事件时,它将加载聚合的当前读取模型。它检查接收到的事件版本是否为预期版本,然后更新读取模型。
这似乎效果很好。问题是当我想拥有EventStore所谓的类别预测时。让我们以订单汇总为例。我可以轻松地设计一个或多个读取模型pr Order。但是,例如,如果我想有一个包含30个客户最后订单的投影,那么我将需要一个类别投影。
我只是在摸索如何做到这一点。我很好奇,是否有其他人正在使用Cassandra和Kafka进行活动采购。我读过一些地方,有些人不赞成这样做。也许这就是原因。
我知道EventStore支持此内置功能。也许使用Kafka作为事件存储将是更好的解决方案。
答案 0 :(得分:1)
使用这种架构,您必须在以下选项之间进行选择:
除非您的系统具有相当高的吞吐量(例如,对于所讨论的流类型,每秒至少10s或100s个事件的持续时间),否则全局流是更简单的方法。某些系统(例如事件存储)具有非常细粒度的流(例如,每个聚合实例),但又可以将它们组合成更大的流(每个流类型/类别/分区,每个多种类型的流等),以开箱即用的性能和可预测的方式实现,而通过仅要求您跟踪单个全局事件位置仍然很简单。
如果您使用Kafka进行分区:
使用全局流消除了这两个方面的顾虑-性能通常可能足够好。
无论哪种情况,您都可能希望将流的位置放入长期事件存储中(例如Cassandra)-您可以通过从事件流(分区的或全局的)中读取专用的进程来做到这一点。使用每个事件的全局或分区位置更新Cassandra中的事件。 (我在MongoDB中也有类似的事情-我有一个过程读取'oplog'并将oplog时间戳复制到事件中,因为oplog时间戳是完全有序的。)
另一种选择是从初始命令处理中删除Cassandra,并改用Kafka Streams:
然后,您将拥有一个下游事件处理器,该事件处理器将事件复制到Cassandra中以便于查询等(并且可以将Kafka流的位置添加到每个事件中,从而进行类别排序)。如果您不想使用Kafka进行长期事件存储,则可以帮助赶上订阅等。 (要赶上进度,您只需从Cassandra中阅读尽可能多的内容,然后从上一个Cassandra事件的位置切换到Kafka的流式播放)。另一方面,Kafka本身可以永久存储事件,因此并不一定总是如此。
我希望这有助于理解您可能会遇到的折衷和问题。