关于使用Apache Kafka Streams 实现事件溯源微服务的问题

Questions about using Apache Kafka Streams to implement event sourcing microservices

事件溯源意味着我们中的许多人构建和开发 Web 应用程序的方式发生了 180 度的转变,它具有很多优势,但也存在许多挑战。

Apache Kafka 是一个很棒的平台,通过其 Apache Kafka Streams API 被宣传为一种工具,允许我们通过其许多功能(解耦、容错、可伸缩性...)来实现此范例: https://www.confluent.io/blog/event-sourcing-cqrs-stream-processing-apache-kafka-whats-connection/

另一方面,有些文章不鼓励我们将它用于事件溯源:https://medium.com/serialized-io/apache-kafka-is-not-for-event-sourcing-81735c3cf5c

这些是我关于 Kafka Streams 作为事件溯源平台的适用性的问题:

  1. 以上文章来自 Jesper Hammarbäck(供职于 serialized.io,一个事件采购平台)。我想得到他提出的主要问题的答案:

    • 正在加载当前状态。在我看来,使用日志压缩和状态存储这不是问题。我说的对吗?

    • 一致写入

  2. 当将某些功能块移动到 Kafka Streams 时,我不确定它们是否适合自然:

    • 身份验证和安全:假设您的客户存储在从客户主题生成的状态存储中。我们应该将他们的密码保存在 topic/store 中吗?听起来不够安全,是吗?那么我们应该如何管理在国营商店拥有客户而在其他地方拥有他们的密码的这方面呢?有什么推荐的好做法吗?

    • Queries:交互式查询是生成数据的可查询视图(按键)的好工具。通过 id 获取实体是可以的,但是 复杂查询(连接) 呢?我们是否需要为每个查询生成状态存储?例如,一家商店按 ID 为客户服务,另一家商店按州为客户服务,另一家商店为去年购买产品的客户服务……这听起来难以管理。另一点是缺少分页:我们如何在查询状态存储时处理大数据集?还有一点,我们不能再进行 动态查询 (如 JPA 条件 API)。这可能会导致 CQRS?复杂性以这种方式不断增长...

    • 数据增长:对于数据库,我们习惯于每个 table 有成千上万的行。 Kafka Streams 应用程序保留一个本地状态存储,该存储会随着时间的推移不断增长。这有多可扩展?本地存储是如何保存的(本地 disk/RAM)?如果它是磁盘,我们应该为应用程序提供足够的 space,如果它是 RAM 足够的内存。

  1. 加载当前状态:博客中描述的机制,关于重新反应当前状态ad-hoc对于单个实体,使用 Kafka 确实会很昂贵。然而,Kafka Streams 遵循将所有对象的当前状态保持在 KTable(即 distributed/sharded)中的理念。因此,从来不需要这样做——当然,它会带来一定的内存成本。

  2. Kafka Streams 基于不同的事件并行化。因此,单个事件的所有交互(处理、状态更新)都由单个线程执行。因此,我不明白为什么会有不一致的写入。

  3. 我不确定确切的要求是什么。在当前的实现中,Kafka Streams 不提供任何存储特定的身份验证或安全功能。不过,为了安全,我们可以做几件事:(a) 加密本地磁盘:这可能是保护数据最简单的事情。 (2) 在将消息放入商店之前,在业务逻辑中加密消息。

  4. Interactive Queries 提供的支持有限,原因有很多(不想详述),而且它从来没有设计为支持复杂查询的目标。这个想法是关于对可以通过简单查找检索到的结果进行急切计算。正如您所指出的,如果您有很多不同的查询,这不是很可扩展(成本密集)。为了解决这个问题,将数据加载到数据库中并让数据库执行它的构建目的是有意义的。 Kafka Streams 本身并不是这个 atm 的正确工具——但是,没有理由不将两者结合起来。

  5. 默认情况下,Kafka Streams 使用 RocksDB 来保存本地状态(您也可以切换到内存存储)。因此,可以写入磁盘并使用非常大的状态。当然,您需要相应地配置您的实例(参见:https://docs.confluent.io/current/streams/sizing.html)。除此之外,Kafka Streams 可水平扩展且完全具有弹性。因此,如果您有大磁盘和足够的实例,您可以在任何时间点添加新实例,从而允许您保存万亿字节的状态。请注意,输入主题分区的数量限制了您可以使用的实例数量(在内部,Kafka Streams 是一个消费者组,您不能拥有比分区更多的实例)。如果这是一个问题,建议首先对输入主题进行过度分区。