对Kafka一次语义感到困惑

时间:2019-08-19 00:51:28

标签: apache-kafka

因此,我一直在阅读有关kafka的一次语义的信息,而我对它的工作方式有些困惑。

我了解生产者如何避免发送重复的消息(以防经纪人的确认失败),但是我不明白的是,在消费者处理消息但在提交之前崩溃的情况下,一次精确的工作原理偏移量。卡夫卡在那种情况下不会重试吗?

2 个答案:

答案 0 :(得分:3)

这是我认为的意思:

  1. 消费者X看到记录Y,并对其执行“操作”,但未提交其偏移量
  2. 消费者X崩溃(仍然没有提交偏移量)
  3. 消费者X重新启动,重新分配了相同的分区(不保证),最终再次看到记录Y

这是完全可能的。但是,要使kafka一次“起作用”,您的所有副作用(状态,输出)也必须进入相同的kafka群集。所以这是要发生的事情:

  1. 消费者X开始交易
  2. 消费者X看到记录Y,发出一些输出记录Z(作为从1开始的交易的一部分)
  3. 消费者X崩溃。在充当交易协调员的经纪人“回滚”(即简化)之后不久,交易开始于1,这意味着其他kafka消费者将再也看不到记录Z
  4. 消费者X重新启动,被分配与以前相同的分区,开始新的交易
  5. 消费者X再次看到记录Y,发出记录Z2(作为从4开始的交易的一部分)
  6. 稍后,消费者X提交其偏移量(作为4中交易的一部分),然后提交该交易
  7. 记录Z2对下游使用者可见。

如果您在同一个kafka集群之外有副作用(例如,不是在记录Z中插入一行,而是在mysql中插入行),则没有通用的方法可以使kafka一次正常工作。您需要依靠老式的重复性和幂等性。

答案 1 :(得分:0)

Radal在回答中很好地解释了这一点,仅在孤立的Kafka集群中一次。

在处理外部数据库(至少是事务性的)时,一种简单的实现一次精确的方法是更新一行(在sgbd事务中),并附上您的业务价值以及它来自的分区/偏移量。这样,如果您的消费者在提交给Kafka之前崩溃了,您将能够获取它处理过的最后一个Kafka偏移量(通过使用Consumer.seek())

尽管在sgbd中可能是相当大的数据开销(为所有行保留偏移量/分区),但是您可能可以进行一些优化。

Yannick