tl; dr; 我正在尝试了解分配了多个分区的单个使用者如何处理到达分区的使用者记录。
例如:
我找到了partition.assignment.strategy
或Ranged
分配器的RoundRobin
配置,但这仅决定了如何为使用者分配分区,而不是确定使用者如何从分配给它的分区中消费。
我开始深入研究KafkaConsumer源 #poll()带我去#pollForFetches() #pollForFetches()然后带我去fetcher#fetchedRecords()和fetcher#sendFetches()
这只是让我尝试一起跟踪整个Fetcher class,也许来晚了,或者我只是没有深入研究,但是我很难弄清消费者的处理方式多个分配的分区。
背景
处理由Kafka Streams支持的数据管道。
在此管道的多个阶段,记录由不同的Kafka Streams应用程序处理,该流由外部数据源加入压缩的主题提要,该外部数据源提供所需的数据,这些数据将在记录中进行扩充,然后继续进行下一阶段的处理
一路走来,有几个空洞的主题,这些记录无法与将增加记录的外部数据源进行匹配。这可能是因为该数据尚不可用(事件或广告系列尚未上线),或者它是错误的数据,将永远不会匹配。
目标是在发布新的扩充数据时重新发布死信主题中的记录,以便我们可以匹配死信主题中以前不匹配的记录,以便对其进行更新并将其发送到下游进行进一步处理。
记录可能多次失败匹配,并且在死信主题中可能有多个副本,因此我们只想重新处理现有记录(在应用程序启动时在最新偏移之前)以及发送到记录的记录。自上次运行该应用程序以来(在先前保存的使用者组偏移量之后)的死信主题。
当消费者在应用程序启动后过滤掉所有到达的记录,并且生产者通过将偏移量作为发布事务的一部分来提交来管理我的消费者组偏移量时,它工作得很好。
但是我想确保我最终会从所有分区中消耗掉,因为我遇到了一个奇怪的情况:未处理的记录将像以前一样在死信主题中被重新处理并降落在同一分区中,从而被过滤掉消费者。尽管没有处理新的记录批次,但仍有一些分区尚未被重新处理。
任何帮助您理解单个使用者如何处理多个分配的分区的帮助。
答案 0 :(得分:2)
您在正确的轨道上看着Fetcher
,因为其中大多数逻辑都在那里。
首先Consumer Javadoc提到:
如果为使用者分配了多个分区以从中获取数据,则它将 会尝试同时有效地从所有人中消费 为这些分区分配相同的使用优先级。
您可以想象,在实践中,需要考虑一些事项。
每次使用方尝试获取新记录时,它将从先前的获取中排除已经有记录等待的分区。在运行中已经具有获取请求的分区也将被排除。
在获取记录时,使用者在获取请求中指定fetch.max.bytes
和max.partition.fetch.bytes
。代理程序使用它们分别确定总计和每个分区返回多少数据。这同样适用于所有分区。
默认情况下,使用这两种方法,消费者将尝试公平地从所有分区中消费。如果不是这种情况,更改fetch.max.bytes
或max.partition.fetch.bytes
通常会有所帮助。