在 Kafka 中使用事件承载状态传输方法时如何确保一致性

How can I assure consistency when using an event-carried state transfer approach in Kafka

让我们假设这样一个简化的场景:

  1. 两个Kafka主题用户订单以及三个微服务 user-service, order-service and shipping-service.

  2. 通过订单服务下订单时,OrderCreated 事件会添加到 orders 主题 并且由 运输服务 收听。该服务需要获取用户信息才能发送订单。根据我的要求,我不能对用户服务进行 REST 调用,而是使用有状态的方法。也就是说,shipping service 是一个 Kafka Streams 应用程序,它监听用户主题,有一个 KTable 由本地存储 支持完整的用户 table 信息。因此,在处理订单时,它已经在本地提供了用户信息。

但是,这种方法的一个问题是运输服务中本地用户信息的一致性,例如:

  1. 用户在用户服务中更新其送货地址,更新其本地 SQL 数据库并使用此更改在用户主题中发布事件。

  2. 用户下单,order-service发布在订单主题

  3. 无论出于何种原因,运输服务都可以在从用户主题读取 UserUpdated 信息之前处理订单主题的 OrderCreated 事件,因此它会使用不再有效的地址。

在这种事件承载状态转移场景下,如何保证发货服务始终有更新的用户信息?

如果您需要顺序保证,您需要将用户信息更新和顺序写入同一主题(特别是写入同一分区),因为 Kafka 仅保证单个分区内的顺序。

您可以使用唯一的用户 ID 作为键调用此主题 "user_action"(用户信息更新和用户订单都是用户操作)。在您的例子中,所有三个服务都将使用 "user_action" 主题。用户服务只考虑用户更新,订单服务只考虑订单,而送货服务两者都考虑。

此博客 post 也可能有帮助:https://www.confluent.io/blog/put-several-event-types-kafka-topic/