280

Although I've come across Kafka before, I just recently realized Kafka may perhaps be used as (the basis of) a CQRS, eventstore.

One of the main points that Kafka supports:

  • Event capturing / storing, all HA of course.
  • Pub / sub architecture
  • Ability to replay the eventlog which allows the ability for new subscribers to register with the system after the fact.

Admittedly I'm not 100% versed into CQRS / Event sourcing but this seems pretty close to what an eventstore should be. Funny thing is: I really can't find that much about Kafka being used as an eventstore, so perhaps I am missing something.

So, anything missing from Kafka for it to be a good eventstore? Would it work? Using it production? Interested in insight, links, etc.

Basically the state of the system is saved based on the transactions/events the system has ever received, instead of just saving the current state / snapshot of the system which is what is usually done. (Think of it as a General Ledger in Accounting: all transactions ultimately add up to the final state) This allows all kinds of cool things, but just read up on the links provided.

4

7 回答 7

320

我是卡夫卡的原作者之一。Kafka 可以很好地用作事件溯源的日志。它具有容错性,可扩展到海量数据,并具有内置的分区模型。

我们在 LinkedIn 将其用于此表单的几个用例。例如,我们的开源流处理系统 Apache Samza内置了对事件溯源的支持。

我认为您没有听到太多关于使用 Kafka 进行事件溯源的消息,主要是因为事件溯源术语在 Kafka 最流行的消费者网络空间中似乎并不流行。

我在这里写了一些关于这种风格的 Kafka 用法。

于 2014-03-23T21:55:38.493 回答
149

Kafka 旨在成为一个消息传递系统,它与事件存储有许多相似之处,但引用它们的介绍:

Kafka 集群会在可配置的时间段内保留所有已发布的消息(无论它们是否已被使用)。例如,如果将保留时间设置为两天,则在消息发布后的两天内,可以使用该消息,之后将丢弃该消息以释放空间。就数据大小而言,Kafka 的性能实际上是恒定的,因此保留大量数据不是问题。

因此,虽然消息可能会被无限期保留,但期望它们将被删除。这并不意味着您不能将其用作事件存储,但使用其他东西可能会更好。查看EventStore以获取替代方案。

更新

卡夫卡文档

事件溯源是一种应用程序设计风格,其中状态更改被记录为按时间排序的记录序列。Kafka 对非常大的存储日志数据的支持使其成为以这种风格构建的应用程序的出色后端。

更新 2

使用 Kafka 进行事件溯源的一个问题是所需主题的数量。通常在事件溯源中,每个实体(例如用户、产品等)都有一个事件流(主题)。这样,可以通过重新应用流中的所有事件来重构实体的当前状态。每个 Kafka 主题由一个或多个分区组成,每个分区存储为文件系统上的一个目录。随着 znode 数量的增加,ZooKeeper 也会有压力。

于 2013-07-23T15:03:26.610 回答
89

我一直回到这个质量检查。而且我没有发现现有的答案足够细致,所以我添加了这个。

TL;博士。是或否,取决于您的事件溯源使用情况。

我知道有两种主要的事件源系统。

下游事件处理器 = 是

在这种系统中,事件发生在现实世界中并被记录为事实。例如跟踪产品托盘的仓库系统。基本上没有冲突的事件。一切都已经发生了,即使是错的。(即托盘 123456 放在卡车 A 上,但原定用于卡车 B。)然后通过报告机制检查事实是否存在异常。Kafka 似乎非常适合这种下游的事件处理应用程序。

在这种情况下,可以理解为什么 Kafka 人提倡将其作为事件溯源解决方案。因为它与已经在例如点击流中使用的方式非常相似。但是,使用术语事件溯源(而不是流处理)的人可能指的是第二种用法......

应用程序控制的事实来源 = 否

作为用户请求通过业务逻辑的结果,这种应用程序声明自己的事件。Kafka 在这种情况下不能很好地工作,主要有两个原因。

缺乏实体隔离

此场景需要能够为特定实体加载事件流。这样做的常见原因是为用于处理请求的业务逻辑构建一个瞬态写入模型。在 Kafka 中这样做是不切实际的。使用 topic-per-entity 可以允许这样做,除非当可能有数千或数百万个实体时,这是一个非首发。这是由于 Kafka/Zookeeper 的技术限制。

以这种方式使用瞬态写入模型的主要原因之一是使业务逻辑更改变得便宜且易于部署。

建议对 Kafka 使用 topic-per-type,但这需要为该类型的每个实体加载事件,只是为了获取单个实体的事件。由于您无法通过日志位置判断哪些事件属于哪个实体。即使使用快照从已知的日志位置开始,如果需要对快照进行结构更改以支持逻辑更改,这可能会产生大量事件。

缺乏冲突检测

其次,由于对同一实体的并发请求,用户可以创建竞争条件。保存冲突事件并在事后解决它们可能是非常不可取的。因此,能够防止冲突事件非常重要。为了扩展请求负载,通常使用无状态服务,同时使用条件写入来防止写入冲突(仅在最后一个实体事件是 #x 时才写入)。又名乐观并发。Kafka 不支持乐观并发。即使它在主题级别支持它,它也需要一直到实体级别才能有效。要使用 Kafka 并防止发生冲突事件,您需要在应用程序级别使用有状态的序列化写入器(每个“分片”或任何 Kafka 的等价物)。这是一个重要的架构要求/限制。

奖励原因:适合问题

添加于 2021 年 9 月 29 日

Kafka 旨在解决大规模数据问题,并且需要相应的开销。应用程序控制的事实来源是一种规模较小的深度解决方案。使用事件溯源以获得良好效果需要精心制作事件和流以匹配业务流程。这通常比通常对系统的其他部分有用的详细程度要高得多。考虑一下您的银行对账单是否包含银行内部流程每个步骤的条目。在确认到您的帐户之前,单笔交易可能有许多条目。

当我问自己与 OP 相同的问题时,我想知道 Kafka 是否是事件溯源的扩展选项。但也许更好的问题是我的事件源解决方案大规模运行是否有意义。我不能对每一个案例都说话,但我认为通常情况并非如此。当这个尺度进入画面时,事件的粒度往往会有所不同。而且我的事件源系统可能应该将更高粒度的事件发布到 Kafka 集群,而不是将其用作存储。

事件溯源仍然需要规模。策略因原因而异。事件流通常具有“完成”状态,如果存储或卷是问题,则可以存档。分片是另一种选择,特别适用于区域或租户隔离的场景。在不太孤立的场景中,当流以可以跨越分片边界的方式任意关联时,分片事件仍然很容易(按流 ID 分区)。但是对于事件消费者来说事情变得更加复杂,因为事件来自不同的分片并且不再是完全有序的。例如,您可以在接收描述所涉及帐户的事件之前接收交易事件。Kafka 也有同样的问题,因为事件只在主题中排序。理想情况下,您设计消费者以便不需要在流之间进行排序。否则,您将采用合并不同的源并按时间戳排序,如果时间戳相同,则使用任意的决胜局(如分片 ID)。服务器的时钟如何不同步变得很重要。

概括

更多信息

你能强迫 Kafka 为应用程序控制的事实来源工作吗?当然,如果您足够努力并足够深入地整合。但这是个好主意吗?不。


每条评论更新

该评论已被删除,但问题类似于:人们使用什么来存储事件?

似乎大多数人在现有数据库之上推出了自己的事件存储实现。对于非分布式场景,如内部后端或独立产品,如何创建基于 SQL 的事件存储有详细的文档说明。在各种数据库之上还有可用的库。还有为此目的而构建的EventStore 。

在分布式场景中,我见过几个不同的实现。Jet 的Panther 项目使用 Azure CosmosDB和 Change Feed 功能来通知侦听器。我在 AWS 上听说的另一个类似实现是使用 DynamoDB 及其 Streams 功能来通知侦听器。分区键可能应该是最佳数据分布的流 id(以减少过度配置的数量)。但是,在 Dynamo 中跨流的完整回放是昂贵的(读取和成本方面)。所以这个 impl 也是为 Dynamo Streams 设置的,用于将事件转储到 S3。当一个新的监听器上线,或者一个现有的监听器想要完整回放时,它会先读取 S3 以赶上。

我当前的项目是一个多租户场景,我在 Postgres 上推出了自己的项目。Citus 之类的东西似乎适合可扩展性,按 tentant+stream 进行分区。

Kafka 在分布式场景中还是很有用的。将每个服务的事件暴露给其他服务是一个不小的问题。事件存储通常不是为此而构建的,但这正是 Kafka 擅长的。每个服务都有自己的内部事实来源(可能是事件存储或其他),但听 Kafka 以了解“外部”发生的事情。该服务还可以向 Kafka 发布事件,以告知“外部”该服务所做的有趣事情。

于 2018-04-17T02:19:24.110 回答
25

您可以将 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 所能提供的。

随意挑战我的答案!你可能不喜欢我所说的关于你最喜欢的具有许多重叠功能的代理,但是,Kafka 并不是设计为事件存储,而是同时作为高性能代理和缓冲区来处理快速生产者和慢消费者场景,例如。

请查看 eventuate.io 微服务开源框架以发现更多关于潜在问题的信息: http: //eventuate.io/

2018 年 2 月 8 日更新

我不会合并评论中的新信息,但同意其中一些方面。本次更新更多是关于微服务事件驱动平台的一些建议。如果您对微服务的健壮设计和总体上可能的最高性能很认真,我将为您提供一些您可能感兴趣的提示。

  1. 不要使用 Spring - 它很棒(我自己经常使用它),但同时又重又慢。而且它根本不是微服务平台。它“只是”一个帮助您实现一个框架(这背后有很多工作......)。其他框架“只是”轻量级 REST 或 JPA 或不同重点的框架。我推荐可能是一流的开源完整微服务平台,它回归纯 Java 根源: https ://github.com/networknt

如果您想了解性能,可以将自己与现有的基准套件进行比较。 https://github.com/networknt/microservices-framework-benchmark

  1. 根本不要使用 Kafka :-)) 这是半开玩笑的。我的意思是,虽然 Kafka 很棒,但它是另一个以代理为中心的系统。我认为未来在无代理的消息系统中。您可能会感到惊讶,但有比 Kafka 系统更快的系统 :-),当然您必须降低到较低级别。看纪事。

  2. 对于事件存储,我推荐名为 TimescaleDB 的高级 Postgresql 扩展,它专注于大容量的高性能时间序列数据处理(事件是时间序列)。当然,CQRS、事件溯源(重播等功能)是开箱即用的 light4j 框架中构建的,它使用 Postgres 作为低存储。

  3. 对于消息传递,请尝试查看 Chronicle Queue、Map、Engine、Network。我的意思是摆脱这种老式的以代理为中心的解决方案,并使用微消息系统(嵌入式)。Chronicle Queue 实际上比 Kafka 还要快。但我同意这不是一个解决方案,你需要做一些开发,否则你去购买企业版(付费版)。最后,从 Chronicle 构建您自己的消息传递层的努力将通过消除维护 Kafka 集群的负担来支付。

于 2017-11-18T20:22:39.717 回答
9

是的,您可以将 Kafka 用作事件存储。它工作得很好,尤其是在引入Kafka Streams时,它提供了一种 Kafka 原生的方式来将您的事件处理成您可以查询的累积状态。

关于:

能够重放事件日志,这允许新订阅者在事后向系统注册。

这可能很棘手。我在这里详细介绍了这一点:https ://stackoverflow.com/a/48482974/741970

于 2018-01-28T17:39:57.897 回答
0

我认为您应该查看 axon 框架以及它们对 Kafka 的支持

于 2020-04-21T19:32:47.800 回答
-1

是的,Kafka 在事件溯源模型(特别是 CQRS)中运行良好,但是您在为主题设置 TTL 时要小心,并始终牢记 Kafka 不是为这种模型设计的,但是我们可以很好地使用它。

于 2019-07-16T23:22:02.667 回答