虽然我以前见过Kafka,但我最近才意识到,Kafka可能被用作cqrs,eventstore的基础。
Kafka支持的要点之一是:
事件捕获/存储,当然了。
发布/子架构
能够重播事件日志,允许新订户在事件发生后向系统注册。
诚然,我不是100%精通cqrs/事件源,但这似乎非常接近eventstore应该是什么。有趣的是:我真的找不到关于Kafka被用作事件商店的太多信息,所以也许我遗漏了什么。
那么,Kafka有没有什么遗漏,让它成为一个好的事件商店?行吗?使用it生产?对见解、链接等感兴趣。
基本上,系统的状态是根据系统曾经接收到的事务/事件来保存的,而不是像通常那样只保存系统的当前状态/快照(把它想象成会计中的总分类账:所有的交易最终加起来就是最终状态)这允许各种各样的酷的东西,但是只要读一下提供的链接就可以了。
4条答案
按热度按时间lxkprmvk1#
您可以使用kafka作为事件存储,但我不建议这样做,尽管它看起来可能是一个不错的选择:
kafka只保证至少交付一次,并且事件存储中存在无法删除的重复项。更新:在这里你可以读到为什么Kafka这么难,以及一些关于如何最终实现这种行为的最新消息:https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it/
由于不可变性,在应用程序发展和事件需要转换时,无法操作事件存储(当然也有向上转换之类的方法,但是…)。曾经可能会说您永远不需要转换事件,但这不是正确的假设,可能会出现这样的情况:您对原始事件进行备份,但您将它们升级到最新版本。这是事件驱动体系结构中的有效需求。
没有地方保存实体/聚合的快照和重播将变得越来越慢。从长远来看,创建快照是事件存储必须具备的功能。
由于kafka分区是分布式的,与数据库相比很难管理和备份。数据库更简单:-)
所以,在你做出选择之前,你要三思而后行。将事件存储作为应用层接口(监视和管理)、sql/nosql存储和kafka作为代理的组合,比让kafka处理这两个角色来创建完整的功能完整解决方案更好。
事件存储是一项复杂的服务,如果您认真考虑在事件驱动体系结构中应用事件源、cqrs、sagas和其他模式并保持高性能,那么它需要的不仅仅是kafka所能提供的服务。
欢迎挑战我的答案!你可能不喜欢我说的你最喜欢的经纪人有很多重叠的功能,但仍然
apeeds0o2#
我一直回到这个问题上。我发现现有的答案不够细致,所以我加上这个。
热释光;医生:是或否,取决于您的活动来源使用情况。
我知道有两种主要的事件源系统。
下游事件处理器=是
在这种系统中,事件发生在现实世界中,并被记录为事实。如仓库系统,以保持跟踪托盘的产品。基本上没有冲突事件。一切都已经发生了,即使是错的(i、 e.将托盘123456放在卡车a上,但计划放在卡车b上。)然后通过报告机制检查事实是否存在异常。Kafka似乎非常适合这种下游的事件处理应用程序。
在这种情况下,Kafka人为什么要把它作为一个事件源解决方案来提倡,这是可以理解的。因为它与click streams中已经使用的方式非常相似。然而,使用事件源(相对于流处理)这个术语的人很可能指的是第二种用法。。。
应用程序控制的真实来源=否
这种应用程序声明自己的事件,作为通过业务逻辑的用户请求的结果。Kafka在这种情况下效果不佳主要有两个原因。
缺乏实体隔离
此场景需要能够加载特定实体的事件流。这样做的常见原因是为业务逻辑构建一个临时写模型,以用于处理请求。这样做在Kafka是不切实际的。使用每个实体的主题可以实现这一点,但当可能有数千或数百万个实体时,这是一个非启动程序。这是由于Kafka/Zookeeper的技术限制。
以这种方式使用临时写模型的一个主要原因是使业务逻辑更改便宜且易于部署。
对于kafka,建议使用topic per type,但这将需要为该类型的每个实体加载事件,以便为单个实体获取事件。因为您不能通过日志位置来判断哪些事件属于哪个实体。即使使用快照从已知的日志位置开始,也可能会有大量的事件需要处理。
缺乏冲突检测
其次,用户可以通过对同一实体的并发请求来创建竞争条件。保存冲突事件并在事后解决它们可能是非常不可取的。因此,重要的是能够防止冲突事件。为了扩展请求负载,通常使用无状态服务,同时使用条件写入防止写入冲突(仅当最后一个实体事件为#x时才写入)。a、 k.a.乐观并发。kafka不支持乐观并发。即使它在主题级别支持它,它也需要一直到实体级别才能有效。要使用kafka并防止冲突事件,您需要在应用程序级别使用有状态、序列化的writer。这是一个重要的体系结构要求/限制。
更多信息
按评论更新
评论已经被删除,但问题是这样的:人们用什么来存储事件?
似乎大多数人都在现有数据库的基础上运行自己的事件存储实现。对于非分布式场景(如内部后端或独立产品),如何创建基于sql的事件存储区是一个很好的文档。在各种各样的数据库上都有可用的库。还有一个eventstore,它就是为此而构建的。
在分布式场景中,我看到了几种不同的实现。jet的panther项目使用azurecosmosdb,并带有changefeed特性来通知侦听器。我在aws上听说的另一个类似的实现是使用dynamodb及其streams特性来通知侦听器。分区键可能应该是最佳数据分发的流id(以减少过度配置的数量)。然而,在dynamo中跨流的完整重放是昂贵的(读取和成本方面)。所以这个impl也是为dynamo流设置的,以便将事件转储到s3。当一个新的监听器联机时,或者一个现有的监听器想要一个完整的重播时,它会读取s3以首先赶上。
我目前的项目是一个多租户的方案,我在postgres上推出了自己的方案。类似citus的东西似乎适合于可伸缩性,通过tentant+stream进行分区。
kafka在分布式场景中仍然非常有用。向其他服务公开每个服务的事件是一个非常重要的问题。事件存储通常不是为这个目的而建立的,但这正是Kafka所擅长的。每个服务都有自己的内部真相来源(可能是事件存储或其他),但倾听Kafka的声音,以了解“外部”正在发生什么。这项服务还可以向Kafka发布事件,向“外界”通报这项服务所做的有趣的事情。
2q5ifsrm3#
Kafka本来是一个消息传递系统,它与事件商店有许多相似之处,但引用他们的简介:
kafka集群保留所有已发布的消息,无论它们是否已在可配置的时间段内被使用。例如,如果保留期设置为两天,则在邮件发布后的两天内,可以使用该邮件,之后将丢弃该邮件以释放空间。kafka的性能在数据大小方面实际上是恒定的,因此保留大量数据不是问题。
因此,尽管消息可能被无限期地保留,但人们期望它们会被删除。这并不意味着您不能将其用作事件存储,但最好使用其他内容。查看eventstore以获取替代方案。
更新
Kafka文献:
事件源是一种应用程序设计风格,其中状态更改记录为按时间顺序排列的记录序列。kafka对非常大的存储日志数据的支持使它成为以这种风格构建的应用程序的优秀后端。
更新2
使用kafka进行事件源的一个问题是所需主题的数量。通常在事件源中,每个实体(如用户、产品等)都有一个事件流(主题)。这样,可以通过重新应用流中的所有事件来重构实体的当前状态。每个kafka主题由一个或多个分区组成,每个分区存储为文件系统上的一个目录。随着znode数量的增加,zookeeper也会施加压力。
yqkkidmi4#
我是Kafka的原作者之一。Kafka将很好地作为事件来源的日志。它是容错的,可扩展到巨大的数据大小,并且具有内置的分区模型。
我们在linkedin使用它来处理这个表单的几个用例。例如,我们的开源流处理系统apachesamza内置了对事件源的支持。
我想你不会听到太多关于使用kafka进行事件源的说法,主要是因为事件源的术语在kafka最流行的消费者web空间中似乎并不流行。
我在这里写了一些关于Kafka这种风格的用法。