Spring Kafka中的事务同步

时间:2017-11-17 15:53:57

标签: spring-transactions spring-kafka

我想将kafka事务与存储库事务同步:

@Transactional
public void syncTransaction(){
  myRepository.save(someObject)
  kafkaTemplate.send(someEvent)
}

由于合并(https://github.com/spring-projects/spring-kafka/issues/373)并且根据文档这是可能的。然而,我有理解和实现该功能的问题。 查看https://docs.spring.io/spring-kafka/reference/htmlsingle/#_transaction_synchronization中的示例,我必须创建一个MessageListenerContainer来监听我自己的事件。 我还需要使用KafkaTemplate发送我的活动吗? MessageListenerContainer是否禁止向代理发送?

如果我理解正确kafkaTemplate和kafkaTransactionManager必须使用相同的producerFactory,我必须在其中启用Transaction设置transactionIdPrefix。在我的示例中,我必须将messageListenerContainer的TransactionManager设置为DataSourceTransactionManager。这是对的吗?

从我的角度来看,通过kafkaTemplate发送一个事件看起来很奇怪,听我自己的事件并再次使用kafkaTemplate转发事件。

如果我能得到一个kafka事务与存储库事务和解释的简单同步的示例,我真的会帮助我。

3 个答案:

答案 0 :(得分:6)

如果监听器容器配置了KafkaTransactionManager,容器将创建一个生产者,该生产者将被任何下游kafka模板使用,容器将为您发送偏移到该事务。

如果容器有其他事务管理器,则容器无法发送偏移量,因为它无权访问生产者(或模板)。

另一个解决方案是使用@Transactional(使用数据源TM)注释您的方法,并使用kafka TM配置容器。

这样,你的DB tx将在线程返回容器之前提交,然后容器将偏移量发送到kafka事务并提交它。

有关示例,请参阅the framework test cases

答案 1 :(得分:2)

@Eike Behrends有一个db + kafka事务,您可以使用ChainedTransactionManager并以这种方式定义它:

@Bean
public KafkaTransactionManager kafkaTransactionManager() {
    KafkaTransactionManager ktm = new KafkaTransactionManager(producerFactory());;
    ktm.setTransactionSynchronization(AbstractPlatformTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
    return ktm;
}


@Bean
@Primary
public JpaTransactionManager transactionManager(EntityManagerFactory em) {
    return new JpaTransactionManager(em);
}

@Bean(name = "chainedTransactionManager")
public ChainedTransactionManager chainedTransactionManager(JpaTransactionManager jpaTransactionManager,
                                                           KafkaTransactionManager kafkaTransactionManager) {
    return new ChainedTransactionManager(kafkaTransactionManager, jpaTransactionManager);
}

您需要注释事务性db + kafka方法@Transactional("chainedTransactionManager")

(你可以在spring-kafka项目上看到问题:https://github.com/spring-projects/spring-kafka/issues/433

你说:

  

从我的角度来看,我发送一个事件看起来很奇怪   kafkaTemplate,听我自己的事件并使用。转发事件   kafkaTemplate再次。

你试过这个吗?如果可以,请提供一个例子吗?

答案 2 :(得分:0)

为了实现您的目标,您应该使用不同的“最终一致”方法,例如 CDC(变更数据捕获)。 Kafka 写入和任何其他系统(例如数据库)之间没有原子事务 - 又名 XA 事务。当您拥有分布式服务(有些人称之为微服务)时,这是一个完整的范式 swift,在您的情况下,这些服务可能通过生产/消费到/从 Kafka 主题进行通信。