微服务中的事务发件箱模式与 ChainedKafkaTransactionManager

Posted

技术标签:

【中文标题】微服务中的事务发件箱模式与 ChainedKafkaTransactionManager【英文标题】:Transactional outbox pattern vs ChainedKafkaTransactionManager in Microservices 【发布时间】:2021-04-08 22:10:00 【问题描述】:

使用 Spring-Kafkas ChainedKafkaTransactionManager 我看不到在 Spring Boot 微服务上下文中实现事务发件箱模式的任何意义。

将消息生产者(即 KafkaTemplate 的 send 方法)和 DB 操作放在同一个事务块中,正好解决了发件箱模式应该解决的问题: 如果事务代码中出现任何异常,则既不会提交数据库操作,也不会在消费者端读取消息(配置为 read_committed)

这样我不需要额外的表格或任何类型的 CDC 代码。总之,Spring Kafka 的事务同步方式对我来说似乎比事务发件箱模式的任何实现更容易使用和实现。

我错过了什么吗?

public ChainedKafkaTransactionManager chainedTransactionManager(
                        JpaTransactionManager transactionManager,
                        KafkaTransactionManager kafkaTransactionManager) 
        ChainedKafkaTransactionManager chainedKafkaTransactionManager = 
            new ChainedKafkaTransactionManager<>(transactionManager, 
                                                 kafkaTransactionManager);
        
        return chainedKafkaTransactionManager;
    

    @Bean
    @Primary
    public JpaTransactionManager transactionManager(EntityManagerFactory 
        entityManagerFactory) 
        JpaTransactionManager jpaTransactionManager = 
                    new JpaTransactionManager(entityManagerFactory);
    
        return jpaTransactionManager;
    

    @Bean
    public KafkaTransactionManager<Object, Object> 
             kafkaTransactionManager(ProducerFactory producerFactory) 
        KafkaTransactionManager kafkaTransactionManager = 
           new KafkaTransactionManager<>(producerFactory);
        
        return kafkaTransactionManager;
    


    @Transactional(value = "chainedTransactionManager")
    public Customer createCustomer(Customer customer) 
        customer = customerRepository.save(customer);
        kafkaTemplate.send("customer-created-topic","Customer created");
          
        return customer;
    

【问题讨论】:

评论:哇,多么棒的一段文字!添加一些注释/段落可能使其更具可读性。还添加一些(伪)源代码可能会吸引知道答案的人。 @H.Hasenack 感谢您的反馈。 Kafka 主题对我来说也是新的。但是万一生产者被链式TM真的需要吗?见docs.spring.io/spring-kafka/docs/2.6.4/reference/html/… 【参考方案1】:

如果您尝试更新的数据在 kafka 外部,您将获得较弱的保证。

请注意,仅在 Kafka Streams 的内部处理范围内保证一次性语义;例如,如果用 Streams 编写的事件流应用程序进行 RPC 调用以更新某些远程存储,或者如果它使用自定义客户端直接读取或写入 Kafka 主题,则无法保证产生的副作用恰好一次。

https://www.confluent.fr/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it/

【讨论】:

【参考方案2】:

我认为它不会为您提供相同级别的安全性。如果 Kafka 提交和 DB 提交之间出现问题怎么办。

https://medium.com/dev-genius/transactional-integration-kafka-with-database-7eb5fc270bdc

【讨论】:

以上是关于微服务中的事务发件箱模式与 ChainedKafkaTransactionManager的主要内容,如果未能解决你的问题,请参考以下文章

架构模式: 轮询发布者

架构模式: 事务日志跟踪

Debezium 发件箱模式 |如果我们使用 debezium,架构是用 SMT/发件箱表固定的吗

使用 Debezium 的 Quarkus 发件箱模式:如何将自定义列添加到发件箱表

Spring Kafka 项目的 Debezium 发件箱错误

发件箱模式 - 我们如何防止消息中继进程生成重复消息?