我继续回到此质量检查。而且我发现现有答案不够细致,因此我添加了这个答案。
TL; DR。是或否,这取决于您的事件源使用情况。
我知道有两种主要的事件源系统。
下游事件处理器=是
在这种系统中,事件发生在现实世界中,并记录为事实。例如用于跟踪产品托盘的仓库系统。基本上没有冲突事件。一切都已经发生,即使它是错误的。(即,托盘123456放在卡车A上,但原定在卡车B上。)然后,通过报告机制检查事实是否存在异常。Kafka似乎非常适合这种下游事件处理应用程序。
在这种情况下,可以理解为什么卡夫卡人提倡将其作为事件采购解决方案。因为它与单击流中已使用的方法非常相似。但是,使用术语“事件源”(而不是“流处理”)的人可能是指第二种用法...
应用程序控制的真理来源=否
由于用户请求通过业务逻辑传递,这种应用程序声明了自己的事件。Kafka在这种情况下不能很好地工作,主要有两个原因。
缺乏实体隔离
这种情况需要能够为特定实体加载事件流。这样做的常见原因是为业务逻辑建立一个瞬态写入模型,以用于处理请求。在Kafka中这样做是不切实际的。使用每个实体的主题可能会允许这样做,但是当可能有成千上万个实体时,这不是入门。这是由于Kafka / Zookeeper中的技术限制所致。
以这种方式使用瞬态写入模型的主要原因之一是使业务逻辑更改便宜且易于部署。
建议不要为Kafka使用每个类型的主题,但这会要求为该类型的每个实体加载事件,只是为了获取单个实体的事件。由于您无法通过日志位置分辨哪些事件属于哪个实体。即使使用快照从已知的日志位置开始,这也可能是大量需要处理的事件。
缺乏冲突检测
其次,由于对同一实体的并发请求,用户可以创建竞争条件。保存冲突事件并在事件发生后解决它们可能是非常不希望的。因此,重要的是能够防止发生冲突的事件。为了扩展请求负载,通常使用无状态服务,同时使用条件写入来防止写入冲突(仅当最后一个实体事件为#x时才进行写入)。又名乐观并发。Kafka不支持乐观并发。即使它在主题级别提供了支持,它也必须一直到实体级别才能生效。要使用Kafka并防止发生冲突的事件,您将需要在应用程序级别使用有状态的序列化编写器。这是一个重要的体系结构要求/限制。
更多信息
每条评论更新
该评论已被删除,但问题是这样的:那么人们将什么用于事件存储?
似乎大多数人都将他们自己的事件存储实现放在现有数据库之上。对于非分布式方案,例如内部后端或独立产品,如何创建基于SQL的事件存储的文档已备有证明。并且在各种数据库之上都有可用的库。还有EventStore,是为此目的而构建的。
在分布式方案中,我已经看到了几种不同的实现。Jet的Panther项目使用Azure CosmosDB和Change Feed功能来通知侦听器。我在AWS上听说过的另一个类似实现是使用DynamoDB及其Streams功能来通知侦听器。分区键可能应该是流ID,以实现最佳的数据分发(以减少过度配置的数量)。但是,在Dynamo中跨流进行完全重播非常昂贵(读取和费用合理)。因此,还为Dynamo Streams设置了此impl以将事件转储到S3。当新的侦听器上线或现有的侦听器要进行完整重播时,它将读取S3以先追赶。
我当前的项目是一个多租户场景,我在Postgres之上建立了自己的项目。像Citus之类的东西似乎适合于可伸缩性,即按帐篷+流进行分区。
Kafka在分布式方案中仍然非常有用。将每个服务的事件公开给其他服务是不平凡的问题。事件存储通常不是为此创建的,但这恰恰是Kafka做得很好的。每个服务都有其自己的内部事实来源(可能是事件存储或其他),但会收听Kafka以了解“外部”正在发生的事情。该服务还可以向Kafka发布事件,以将“有趣的事情”通知“外部”。