【问题标题】:Spring Kafka transaction commit sequenceSpring Kafka 事务提交序列
【发布时间】:2021-10-31 06:50:57
【问题描述】:

我有两个服务。用户调用 Service-A 的 REST 端点,该端点进行处理,在数据库中创建记录/条目,然后发送 Kafka 事件以便使用 Service-B。

我已经使用@Transactional 进行了注释,以便数据库提交和Kafka 提交同时发生。

Service-B 将接收 Kafka 事件,处理,并将更新后的事件发送回 Service-A。

在这种情况下,我看到 Service-A 中的某些更新失败,表明找不到记录/条目。是竞赛条件吗?

由于ChainedKafkaTransactionManager 已被弃用,我如何确保首先发生数据库提交,然后是 Kafka 提交?

“对于生产者发起的事务,随着事务同步,Kafka提交也会发生在DB之后。”来自加里·拉塞尔

在我的场景中,由于事务不是由 Kafka 发起的,我该如何撤销提交?

@Transactional("dstm")
public void someMethod(String in) {
  Employee employee = this.repository.save(new Employee(in));
  if(employee.isSomeCondition()) {
    sendToKafka(employee);
  }
}

【问题讨论】:

    标签: spring-kafka spring-transactions


    【解决方案1】:

    其实这里有一个很好的例子,你可以在这里配置多个数据源的事务处理:https://docs.spring.io/spring-kafka/docs/current/reference/html/#ex-jdbc-sync

    另一个可能导致问题的问题是您的消费者的隔离级别。你把它改成 read_committed 了吗?

    【讨论】:

    • 即使在这些示例中,我也看到 Kafka 提交首先发生。就我而言,我需要创建一个新记录,如果它属于某种类型,那么我需要通知另一个系统。
    • 在生产者发起的 tx 中,您可以完全控制 tx 排序。这实际上不是卡夫卡特有的。您可以做的是调试您的应用程序并检查 kafka tx 是否在 db 事务之前启动。检查 transactionIntercepor 并验证相应的 plattformTransactionManager
    • 在我的例子中,事务是由数据源事务管理器发起的,用示例代码更新了问题。我无法使用 Kafka 事务管理器发起事务,因为在某些情况下甚至不会发送消息/事件。
    • 如果你想让Kafka事务先提交,使用本地事务。请参阅 KafkaTemplate.executeInTransaction()。
    • @GaryRussell 我想先提交数据库事务以避免竞争条件(数据库提交仍在进行中,并且已经收到事件的响应,并且处理该事件记录在数据库中仍然不可用)
    猜你喜欢
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 2019-11-25
    • 1970-01-01
    • 2015-12-17
    相关资源
    最近更新 更多