在Confluent Cloud上使用Kafka时,我发现一种奇怪的行为。我创建了一个默认分区值为6的主题。
我的系统由一个Java Producer应用程序和一个Kafka Streams应用程序组成,该Java Producer应用程序向该主题发送消息,而Kafka Streams应用程序从该主题读取并对每条消息执行操作。
----------------------- -------- -----------
| Kafka Java Producer | ----> | topic | ----> | KStream |
----------------------- -------- -----------
目前,我仅启动Kafka Streams应用程序的一个实例,因此使用者组只有一个成员。
这是我观察到的:
KStream
events.foreach { key, value ->
logger.info("--------> Processing TimeMetric {}", value)
//Store in DB
登录
[-StreamThread-1] uration$$EnhancerBySpringCGLIB$$e72e3f00 : --------> Processing Event {"...
events-processor-19549050-d8b0-4b39...
。如前所述,该组只有一个成员(KStream的唯一实例)。但是,如果显示该组在分区2中的一条消息之后。此外,请注意,当前偏移量似乎是1,结束偏移量是2): [-StreamThread-1] uration$$EnhancerBySpringCGLIB$$e72e3f00 : --------> Processing Event {
尽管处理似乎很好,但是上面显示的状态没有多大意义。您能解释一下原因吗?
答案 0 :(得分:0)
对于第一个问题,有两种可能性(尽管通过阅读第二个问题,看来您正在使用交易):
如果您不使用精确一次语义,则生产者可能会发送多个消息,因为根本无法控制发送之前。这样,由于这些重复的消息,Kafka的默认至少一次语义可能会使偏移量增加> +1。
如果您使用完全一次语义或交易,则出于内部控制目的,每次交易事件都会在该主题中写入标记。这些标记负责+2的增加,因为它们也存储在主题中(但消费者避免使用)。 Confluent's guide to transactions还具有有关此行为的一些信息:
生产者发起提交(或中止)后,协调者 开始两阶段提交协议。
在第一阶段,协调器将其内部状态更新为 “ prepare_commit”并在事务日志中更新此状态。一旦 这样就保证了交易无论如何都将被落实 什么。
然后,协调器开始阶段2,在该阶段中编写事务 将标记提交到主题分区,该主题分区是 交易。
这些交易标记未公开给应用程序,但是 使用者在read_committed模式下用于过滤来自 中止交易并且不返回开放消息的一部分 交易(即那些在日志中但没有 与它们相关联的交易标记)。
一旦标记被写入,交易协调器就会标记 交易为“完成”,生产者可以开始下一个 交易。
通常来说,您不必关心偏移号,因为它不是确定的指南。例如,重试,重复或交易标记会使偏移量与您期望查看生产者的偏移量有所不同,但您不必为此担心。您的消费者会,并且他们只会处理“真实”消息。
关于问题2,这是一个已知问题:https://issues.apache.org/jira/browse/KAFKA-6607
引用吉拉语
使用以下命令为Kafka Streams应用程序输入输入主题时 交易, Kafka Streams不会提交“ endOffset”,而是“ endOffset” -如果到达主题末尾则为1”。。原因是提交标记是主题中的最后一个“消息”;流提交了“偏移量 最后处理的邮件加1“,并且不将提交标记放入 帐户。
这不是正确性问题,但是当检查消费者的滞后时 通过bin / kafka-consumer.group.sh,延迟显示为1而不是0 – 从消费者组工具的角度来看,什么是正确的。
希望有帮助!