Kafka Stream:线程之间的再平衡是如何工作的?

Kafka Stream: How does rebalancing works between threads?

我有以下 Kafka 流设置

  1. 输入主题有 6 个分区
  2. Stream 应用程序有 6 个线程。
  3. 应用程序的单个实例目前是 运行。
  4. 拓扑有一个内存状态存储,由更新日志主题支持。
  5. 我们使用恰好一次语义,所有其他属性都默认。
  6. 输入主题中的数据使用键进行分区。分区是可重现的。 IE。相同的键总是会给出相同的分区。

如果我没理解错的话,在这样的设置下,

  1. 拓扑中的每个线程将各自分配一个分区。
  2. 状态存储在线程本地,其他线程看不到它。
  3. 状态存储也分区为 6 == 线程数。
  4. 我通过运行本地申请确认了以上内容。

到目前为止一切顺利,但我们的生产最近出现了各种网络中断,导致代理无法相互通信。这里的事情变得有点棘手且难以理解.我们在发生这种情况后的 5 秒内收到了以下警报

[Consumer clientId=6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-1-consumer, groupId=v11] 
Offset commit failed on partition topic.v5-0 at offset 180855: The coordinator is not aware of this member.
severity: ERROR
thread: 6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-1
logger: org.apache.kafka.clients.consumer.internals.ConsumerCoordinator
Show more



[Consumer clientId=6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-2-consumer, groupId=v11] 
Offset commit failed on partition topic.v5-0 at offset 189332: The coordinator is not aware of this member.
thread: 6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-2
logger: org.apache.kafka.clients.consumer.internals.ConsumerCoordinator
Show more


[Consumer clientId=6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-6-consumer, groupId=v11] 
Offset commit failed on partition topic.v5-0 at offset 340410: The coordinator is not aware of this member.
thread: 6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-6
logger: org.apache.kafka.clients.consumer.internals.ConsumerCoordinator
Show more


[Consumer clientId=6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-1-consumer, groupId=v11] 
Offset commit failed on partition topic.v5-0 at offset 344410: The coordinator is not aware of this member.

thread: 6b4fcfec-c94a-4a35-b37a-f7755f45415d-StreamThread-1
logger: org.apache.kafka.clients.consumer.internals.ConsumerCoordinator
Show more

从这里看来,同一个分区被多个线程读取,或者 Kafka 将线程中的消费者标记为 FAILED,然后将处理移至下一个消费者,依此类推。这里有几处我不明白。

  1. 流线程 2 已经订阅了另一个分区,它的状态存储会发生什么情况? Stream 线程 1 中的状态存储是否合并到第二个中?
  2. Kafka 是否停止使用来自线程 1 的消息然后移动状态?
  3. stream-1 是在一段时间后再次开始处理它的分区,还是永远移动这个分区的处理?

我问这个问题的原因是当我查看更新日志主题时看到以下行为。

  1. 输入主题对所有分区的延迟为 0。
  2. 更改日志反映同一输入记录被多次应用。这是可以理解的,因为我们使用的是 at least once 语义。
  3. 但是最终状态存储不准确。仅当两个流线程正在更新相同的变更日志分区,或者状态存储中的状态未完全刷新到变更日志主题时,才能解释不准确

任何人都可以帮助我了解 Kafka 在这种情况下如何重新平衡流应用程序以及是否存在与此相关的任何已知错误?

Streams 再平衡协议非常复杂,有几篇博文比我能更好地解释它:rebalance protocol and static membership

关于流线程可能失败的原因的快速回答是,当线程无法与组协调器通信时,无论出于何种原因,它都会被踢出组并重新分配其任务。如果只是网络问题,线程可以在重新加入组后恢复并重新分配任务。

从阅读您的问题来看,您似乎真的很想知道为什么最终状态存储不准确。如果 at least once 中存在诸如网络分区之类的错误,则不能保证状态未损坏,线程可能不会意识到它不在组中并继续处理。为此,您需要 EOSEOS_beta 在最近的版本中确实有更好的性能。