Java 关于故障点,如何分别确保生产者和消费者应用程序之间的kafka事务同步?

Java 关于故障点,如何分别确保生产者和消费者应用程序之间的kafka事务同步?,java,spring,apache-kafka,spring-kafka,Java,Spring,Apache Kafka,Spring Kafka,我对春天的卡夫卡还是有点陌生。我的问题相当简短。我有一个消费者专用的应用程序,它不断地从Kafka读取消息,处理消息,并使用Ack侦听器手动确认消息。我有来自上游生产者专用应用程序的依赖项,在该应用程序中,他们负责向卡夫卡主题发送消息,以便我使用。我们最近在生产者和消费者之间实现了事务,但我想了解更多关于故障点的信息,以及如何处理回滚的事务,以使它们不会丢失?我已经了解到,最好使用AfterRollbackProcessor而不是SeektocurInterrorHandler处理kafka容器

我对春天的卡夫卡还是有点陌生。我的问题相当简短。我有一个消费者专用的应用程序,它不断地从Kafka读取消息,处理消息,并使用Ack侦听器手动确认消息。我有来自上游生产者专用应用程序的依赖项,在该应用程序中,他们负责向卡夫卡主题发送消息,以便我使用。我们最近在生产者和消费者之间实现了事务,但我想了解更多关于故障点的信息,以及如何处理回滚的事务,以使它们不会丢失?我已经了解到,最好使用
AfterRollbackProcessor
而不是
SeektocurInterrorHandler
处理kafka容器工厂上的事务,同时将
StatefulRetry
设置为true。我使用事务的原因是为了在其较新版本中实现完全相同的Kafka语义,因为我们处理大量的数据库持久性,并且由于DB约束,无法承受重复的事务。我想知道我的
@KafkaListener
是否必须用
@Transactional
注释,因为我之前读过一篇文章,说不应该这样,但其他文章说可能是这样,这就是我不确定的原因。我看到了许多关于生产者和消费者应用程序的问题,但我没有看到关于分别具有这些独立角色的独立应用程序的问题(即使在一天结束时可能是同一件事)。简而言之,我只是想知道在与Kafka合并事务时,什么是最佳实践,以及在这种情况下如何处理失败

Kafka事务对于仅限消费者的应用程序来说是不必要的开销。事务仅在生成记录时有用

我使用事务是为了在其较新版本中实现一次Kafka语义,因为我们需要处理大量数据库持久性,并且由于数据库限制,无法承受重复事务

当涉及其他技术时,不保证“仅一次”。只适用于一次

read->process->write
读写都是卡夫卡的场景。这是一个常见的误解

此外,即使卡夫卡只读/处理/写,“恰好一次”语义也只适用于整个shebang。i、 例如,仅当写入成功时才提交读取的偏移量

过程
步骤将至少获得一次语义,因此无论是否存在卡夫卡写入步骤,以及(如果存在卡夫卡写入)您在该过程步骤的其他位置写入事务时,都需要重复数据消除逻辑

对于从Kafka读取数据并写入数据库而不写入Kafka的情况,侦听器上的
@Transactional
是正确的方法(使用重复数据消除逻辑以避免重复)

对于只需要一次Kafka语义(读/处理/写),但也要在处理步骤中写入DB的情况,可以在侦听器容器中使用
ChainedKafkaTransactionManager
,以便DB事务与Kafka事务同步(但对于DB提交成功但Kafka事务失败的情况,仍然有一个小窗口)。因此,即使在这种情况下,您仍然需要重复数据消除逻辑。在这种情况下,您不需要侦听器上的
@Transactional

编辑

Producer only有点不同;假设您希望在一个事务中发布10条记录,您希望所有记录都在(提交)或(回滚)中。然后您必须使用事务

事务中生成的记录的使用者应该具有
隔离。level=read\u committed
,这样他们就不会看到未提交的写入(默认值为
read\u uncommitted

如果一次只发布单个记录,并且不涉及其他事务资源,那么如果只涉及Kafka,那么使用事务就没有什么意义

但是,如果您正在从DB或JMS等读取数据,并向Kafka写入数据,则可能需要同步DB和Kafka事务,但重复的概率仍然不是零;如何处理这一问题取决于提交事务的顺序

通常,重复数据消除取决于应用程序;通常使用应用程序数据中的某个键,因此,例如,SQL INSERT语句以数据库中尚未存在的键为条件

Kafka为每条记录提供了一个方便的唯一键,并结合了主题/分区/偏移量。您可以将这些键与数据一起存储在数据库中,以防止重复

EDIT2

SeekToCurrentErrorHandler
(STCEH)通常在不使用事务时使用;当侦听器抛出异常时,错误处理程序会重置偏移量,以便在下次轮询时重新提取记录。经过多次尝试后,我们放弃并调用“恢复程序”,例如,
DeadLetterPublishingRecoverer
,将失败的记录写入另一个主题

但是,它仍然可以用于事务

错误处理程序在事务范围内调用(
回滚之前),因此,如果它抛出异常(除非恢复程序“消耗”故障,否则它会抛出异常),事务仍将回滚。如果恢复成功,事务将提交

AfterRollback处理器(ARP)是在恢复功能添加到STCEH之前添加的。它基本上与STCEH完全相同,但在事务范围之外运行(回滚之后)

两种配置都不起作用