【问题标题】:Group send kafka message and DB update in one Transaction in SpringBoot在 Spring Boot 中的一个事务中组发送 kafka 消息和数据库更新
【发布时间】:2020-02-16 23:46:06
【问题描述】:

我需要在一个事务中执行多个操作

  • 产生卡夫卡消息
  • 更新表 A
  • 更新表 B

我可以发送消息并且不更新两个表(A 和 B)。我不能生成消息并更新其中一个表。

我正在尝试使用@Transactional 注释来实现我的目标


import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE)
    public void handle(Event approvalEvent) {
        var entity = entityService.getLatestVersion(approvalEvent.getTransactionId());

        entityService.approve(entity.getTransactionId());
        logService.logApproval(entity);
        producer.send(approvalEvent);
    }

我做得对吗?

【问题讨论】:

    标签: spring-boot apache-kafka spring-data-jpa spring-transactions


    【解决方案1】:

    上述方法的问题在于,您在一个事务中与两个不同的系统(数据库和消息队列)进行交互。当在一个系统上运行成功而在另一个系统上运行失败时要处理的场景组合使解决方案变得复杂。

    微服务领域有一种模式可以处理完全相同的场景。它被称为发件箱模式。

    您可以阅读更多关于它的信息here

    简短的总结是您的数据库中有一个名为 outbox 的附加表,其中包含要发布到消息队列的消息。

    在用于添加\更新实体的数据库事务中,您在发件箱表工具中插入一行,其中包含对该实体的操作的详细信息。

    然后您从发件箱表异步读取行并通过轮询或使用更改数据捕获发布到消息队列。请参阅使用 debezium 的示例实现 here

    您的交易代码如下所示。

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE)
    public void handle(Event approvalEvent) {
        var entity = entityService.getLatestVersion(approvalEvent.getTransactionId());
    
        entityService.approve(entity.getTransactionId());
        logService.logApproval(entity);
        //Outbox is the table containing the records to be published to MQ 
        outboxRepo.save(approvalEvent);
    }
    

    【讨论】:

    • 我不太明白为什么outbox pattern 有优势。我的解决方案是幂等且可水平扩展的。我唯一需要的:如果 kafka 生产者引发异常,则回滚两个数据库事务。我可以重复交易,直到 kafka 重新上线。发件箱模式有同样的问题:读取和更新数据库,发送到队列。 #2 microservices.io/patterns/data/transactional-outbox.html 在没有冗余数据库过载的情况下很难横向扩展。
    • 关键是您要让对事件感兴趣的其他第三方与您的事件更新/插入事务分离。假设您是否需要对日志服务进行一些审计和/或日志记录,您不能将所有这些都添加到您的事务方法中。这都是独立的异步操作,不应影响/延迟数据库事务。
    • debezium 看起来很有前途。谢谢,我去看看!
    猜你喜欢
    • 2014-11-05
    • 1970-01-01
    • 2018-07-21
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 2021-06-12
    相关资源
    最近更新 更多