将 kafka 与 jpa 一起使用时的良好做法

2022-09-03 14:32:26

我目前在一个使用JPA和Kafka的项目中。我试图找到一套结合这些操作的良好实践。

在现有代码中,生产者与jpa用于同一事务中,但是,从我所读到的内容来看,它们似乎没有共享事务。

@PostMapping
@Transactional
public XDto createX(@RequestBody XRequest request) {
    Xdto dto = xService.create(request);
    kafkaProducer.putToQueue(dto, Type.CREATE);
    return dto;
}

其中,kafka 生产者定义如下:

public class KafkaProducer {
    @Autowired
    private KafkaTemplate<String, Type> template;

    public void putToQueue(Dto dto, Type eventType) {
        template.send("event", new Event(dto, eventType));
    }
}

这是组合 jpa 和 kafka 的有效用例吗,事务边界定义是否正确?


答案 1

当事务失败时,这将不会按预期工作。kafka交互不是交易的一部分。

您可能希望查看 TransactionalEventListener 您可能希望将消息写入 AFTER_COMMIT 事件的 kafka。即便如此,kafka的发布也可能失败。

另一种选择是像你一样使用jpa写入数据库。让 debezium 从数据库中读取更新的数据,并将其推送到 kafka。该活动将采用不同的形式,但要丰富得多。


答案 2

通过查看您的问题,我假设您正在尝试实现OLTP系统的CDC(更改数据捕获),即记录要进入事务数据库的每个更改。有两种方法可以解决这个问题。

  1. 应用程序代码对事务数据库和 Kafka 执行双重写入。它不一致并妨碍性能。不一致,因为当您对两个独立的系统进行双重写入时,当任何一个写入失败时,数据就会被搞砸,并且在事务流中将数据推送到Kafka会增加延迟,您不希望在此上妥协。
  2. 从数据库提交中提取更改(数据库/应用程序级触发器或事务日志)并将其发送到 Kafka。它非常一致,完全不会影响您的交易。一致,因为数据库提交日志是成功提交后数据库事务的反映。有很多解决方案可以利用这种方法,如databusmaxwelldebezium等。

如果 CDC 是您的使用案例,请尝试使用任何可用的解决方案。


推荐