Spring Kafka(进而是Spring Cloud Stream)允许我们创建事务性生产者和处理者。我们可以在以下示例项目之一中看到该功能的实际作用:https://github.com/spring-cloud/spring-cloud-stream-samples/tree/master/transaction-kafka-samples:
@Transactional
@StreamListener(Processor.INPUT)
@SendTo(Processor.OUTPUT)
public PersonEvent process(PersonEvent data) {
logger.info("Received event={}", data);
Person person = new Person();
person.setName(data.getName());
if(shouldFail.get()) {
shouldFail.set(false);
throw new RuntimeException("Simulated network error");
} else {
//We fail every other request as a test
shouldFail.set(true);
}
logger.info("Saving person={}", person);
Person savedPerson = repository.save(person);
PersonEvent event = new PersonEvent();
event.setName(savedPerson.getName());
event.setType("PersonSaved");
logger.info("Sent event={}", event);
return event;
}
在此摘录中,有个Kafka主题的读物,一个数据库中的写操作和另一个Kafka主题的另一个写信,所有这些都是事务性的。
我想知道并想回答的是,从技术上如何实现和实施。
由于数据源和Kafka不参与XA事务(两阶段提交),因此该实现方式如何保证本地事务可以从Kafka读取,提交到数据库并以事务方式将所有这些内容写入Kafka? / p>
答案 0 :(得分:1)
没有保证,仅在Kafka本身内。
Spring提供了事务同步,因此提交紧密并存,但DB可以提交而Kafka可以不提交。因此,您必须应对重复的可能性。
直接使用spring-kafka时,正确的方法不是与@Transactional
一起使用,而是在侦听器容器中使用ChainedKafkaTransactionManager
。
请参见Transaction Synchronization。
另请参阅Distributed transactions in Spring, with and without XA和“尽力而为1PC模式”作为背景。
但是,对于Stream,不支持链式事务管理器,因此,@Transactional
是必需的(对于DB事务管理器)。这将提供与链式tx管理器类似的结果,首先在Kafka之前提交数据库。