Spring boot spring boot中的事务同步与数据库+;卡夫卡的例子

Spring boot spring boot中的事务同步与数据库+;卡夫卡的例子,spring-boot,spring-data-jpa,spring-kafka,Spring Boot,Spring Data Jpa,Spring Kafka,我想用SpringBoot编写一个新的应用程序,使用MySQL+Mango数据库和SpringKafka消息 我尝试使用许多POC来同步Kafka和DB之间的事务,但在某些情况下失败了,我还搜索了许多存储库和博客,以获得至少一个示例。我现在还没有得到任何例子 如果有人给出至少一个示例或配置,这将是将来所有人的一个很好的参考。给你 @springboot应用程序 公共类SO56170932应用程序{ 公共静态void main(字符串[]args){ SpringApplication.run(S

我想用SpringBoot编写一个新的应用程序,使用MySQL+Mango数据库和SpringKafka消息

我尝试使用许多POC来同步Kafka和DB之间的事务,但在某些情况下失败了,我还搜索了许多存储库和博客,以获得至少一个示例。我现在还没有得到任何例子

如果有人给出至少一个示例或配置,这将是将来所有人的一个很好的参考。

给你

@springboot应用程序
公共类SO56170932应用程序{
公共静态void main(字符串[]args){
SpringApplication.run(So56170932Application.class,args);
}
@豆子
公共应用程序运行程序(KafkaTemplate模板){
返回args->template.executeInTransaction(t->t.send(“so56170932a”,“foo”);
}
@豆子
公共链KafkaTransactionManager chainedTm(KafkaTransactionManager ktm,
数据源事务管理器(dstm){
返回新的ChainedKafkaTransactionManager(ktm、dstm);
}
@豆子
公共数据源TransactionManager dstm(数据源数据源){
返回新的数据源TransactionManager(数据源);
}
@豆子
公共并发kafkaListenerContainerFactory kafkaListenerContainerFactory(
ConcurrentKafkaListenerContainerFactoryConfigurer配置器,
卡夫卡消费工厂,
ChainedKafkatTransactionManager(ctm){
ConcurrentKafkListenerContainerFactory=新ConcurrentKafkListenerContainerFactory();
configurer.configure(工厂、卡夫卡消费工厂);
factory.getContainerProperties().setTransactionManager(ctm);
返回工厂;
}
@组成部分
公共静态类侦听器{
私有最终JdbcTemplate JdbcTemplate;
私人最终卡夫卡模板卡夫卡模板;
公共侦听器(JdbcTemplate JdbcTemplate、KafkaTemplate KafkaTemplate){
this.jdbcTemplate=jdbcTemplate;
this.kafkaTemplate=kafkaTemplate;
}
@卡夫卡列斯汀(id=“so56170932a”,topics=“so56170932a”)
公共无效列表1(字符串输入){
这个.kafkaTemplate.send(“so56170932b”,在.toUpperCase()中);
这个.jdbcTemplate.execute(“插入到so56170932(数据)值中(““+in+”)”);
}
@卡夫卡列斯汀(id=“so56170932b”,topics=“so56170932b”)
公共void列表2(字符串输入){
系统输出打印项次(输入);
}
}
@豆子
公共新拓扑(){
返回TopicBuilder.name(“so56170932a”).build();
}
@豆子
公共新主题{
返回TopicBuilder.name(“so56170932b”).build();
}
}


例如,谢谢@GaryRussell。我有两个问题。我正在docker中为此应用程序创建多个实例,因此每个实例的事务前缀id应该相同还是不同?2.我要同步4个事务(DataSourceTransactionManager、PlatformTransactionManager-实体管理器、JpaTransactionManager和KafkartransactionManager的默认设置),可以吗?1。为了正确处理僵尸围栏,它们应该是相同的;实际事务id由前缀、使用者组、主题和分区组成。然后,如果一个实例发生故障,Kafka可以正确地处理重新平衡后移动到另一个实例的分区。2.对但你必须决定顺序;通常,为了避免失败后丢失消息,您需要先使用Kafka(因此它的提交是最后一次);您的代码将需要处理提交到一个或多个DBs的重复交付的可能性。我在docker中有一个Kafka代理,如果我使用相同的事务id前缀连接了多个spring-boot实例,那么它偶尔会给出producedFencedException,并且事务将不起作用。但如果我给不同的事务id前缀,那么它的工作就可以了。为什么会这样?有什么我不知道的吗!如果在侦听器容器线程上生成消息,则
事务.id
。由于一个分区不能分配给多个实例,
transactional.id
s将是唯一的。如果您在容器线程的上下文之外生成消息,
transactional.id
(因此前缀)在实例之间必须是唯一的。如果你同时做这两件事,你将需要两个不同的生产工厂。如果这不能回答您的问题,请提出一个显示代码和配置的新问题。
spring.datasource.url=jdbc:mysql://localhost/integration?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.properties.isolation.level=read_committed

spring.kafka.producer.transaction-id-prefix=tx-

logging.level.org.springframework.transaction=trace
logging.level.org.springframework.kafka.transaction=debug
logging.level.org.springframework.jdbc=debug
mysql> select * from so56170932;
+------+
| data |
+------+
| foo  |
| foo  |
| foo  |
| foo  |
| foo  |
| foo  |
| foo  |
| foo  |
| foo  |
+------+
9 rows in set (0.00 sec)