使用Kafka作为事件存储工作正常,它很容易将消息保留设置为无限制。
但是我看到一些关于Kafka被用于事件采购的报道。 这就是我对如何做到这一点感到困惑的地方。 作为一个活动商店,我可以在那里推送我的消息。并根据需要消费或重播。
但对于事件采购,您很可能希望读取给定实体/聚合ID的事件。 您当然可以使用分区,但这似乎滥用了这个概念,实际添加新实体很难,因为分区计数更多是在静态方面,即使您可以更改它。 那里有没有明智的解决方案? Apache Kafka文档本身只是简单地提到了事件采购。
答案 0 :(得分:0)
关于您对其他问题的评论:
感谢您的努力,但答案却非常偏离主题。 “这真的是你要表达的吗?”不。问题不在于DDD和CQRS。我对这些很熟悉。我问如何或如果我可以使用Kafka进行活动。假设我有1000万个实体,我可能不想让它们一次性跨服务器加载到内存中。我可以使用Kafka加载所有内容来加载单个聚合的数据吗?
答案是肯定的:您可以使用Kafka Streams来处理事件。您的流逻辑会生成聚合并将它们存储在本地状态存储(RocksDB)中,因此生成的聚合不需要在内存中,并且可以在不重放所有事件的情况下进行访问。您可以使用Interactive Queries API访问这些聚合。这太好了!此时,编写可重放的事件处理逻辑是easier said than done,但绝不是不可能的。
答案 1 :(得分:-2)
我认为Apache Kafka是存储事件采购事件的最佳解决方案。事件采购的概念非常接近,通常与Greg Young的名为CQRS的概念/实践一起使用,我建议你研究。
我在这个答案中使用的术语存储库是一个关于域驱动设计的存储库,如Eric Evans一书中那样。
我想我知道你有这种困惑的原因是什么。
但对于事件采购,您很可能希望阅读给定实体/聚合ID的事件。
你的问题的上述内容在我看来是正确的。但是我认为你想要表达不同的东西。你想表达这样的话:
在事件源中,当要求存储库从其数据源检索对象时,存储库必须检索在存储库的每个请求中构成特定实体的所有事件。然后必须重播这些事件以构建对象。
这是你想表达的吗?因为上面的句子在我看来是 false 。
每次检索时都不需要重建对象。
换句话说,每次从存储库中检索对象时,都不需要重放构成对象的所有事件。您可以在对象上播放事件并以不同的方式存储对象的当前版本,例如在缓存中,甚至更好,在缓存和卡夫卡中。
让我们举个例子吧。我们假设我们有一个装载和卸载的轨道/卡车。
活动的主要流程将是操作 - 这将是我们应用中的第一个kafka主题。这将是我们的真相来源,因为Jay Kreps通常会将其作为他的论文。
这些是事件:
最终结果是曲目1充满了花朵,曲目2充满了沙子。
您所做的是阅读本主题中的事件并填充您的第二个主题: trackUpdated 。您流入 trackUpdated 主题的事件如下:
同时,消耗每条消息后,您可以在缓存中更新卡车的当前版本,例如memcached的。因此,memcache将成为存储库用于检索跟踪对象的直接源。
您还可以将 trackUpdated 主题变为压缩主题。
阅读Apache Kafka官方文档中的压缩主题。在Confluent博客和Linkedin工程博客上有很多有关它的相关材料(在Confluent公司开始之前)。
因为 trackUpdated 被编译,Kafka在一段时间后看起来像这样:
如果您使用曲目ID作为所有消息的密钥,Kafka将执行此操作 - 在文档中读取消息" keys"是。因此,每首曲目最终会收到1条消息。如果您在应用中发现错误,则可以重播操作主题以再次填充缓存和 trackUpdated 主题。如果您的缓存出现故障,您可以使用 trackUpdated 主题填充缓存。
你怎么看?投票和评论受到高度欢迎。(1)经过一番思考之后,我改变了主意,引用你的话是真的。我现在发现它是假的。所以我不这样做((认为用于事件采购,你很可能想要读取给定实体/聚合ID的事件。
当您在代码中发现错误时,您希望重播所有对象的所有事件。如果我的简单示例中有2个实体或者有10M实体,则无关紧要。
事件采购不是要检索特定实体的所有事件。事件采购是指您拥有所有事件的审核日志,并且您可以重播它们以重建您的实体。您不需要能够重建单个特定实体。
(2)强烈建议熟悉Confluent和LinkedIn工程博客的一些博客文章。以下对我非常感兴趣:
https://www.confluent.io/blog/making-sense-of-stream-processing/
官方Kafka Docs也是必须的。