无法在具有多个主题分区的Kafka Streams中重新平衡错误

时间:2017-02-19 15:57:31

标签: apache-kafka apache-kafka-streams

当源主题分区计数= 1时工作正常。如果我将分区提升到任何值> 1,我看到以下错误。适用于低级别以及DSL API。有什么指针吗?可能会遗漏什么?

org.apache.kafka.streams.errors.StreamsException: stream-thread [StreamThread-1] Failed to rebalance
        at org.apache.kafka.streams.processor.internals.StreamThread.runLoop(StreamThread.java:410)
        at org.apache.kafka.streams.processor.internals.StreamThread.run(StreamThread.java:242)

Caused by: org.apache.kafka.streams.errors.StreamsException: task [0_1] Store in-memory-avg-store's change log (cpu-streamz-in-memory-avg-store-changelog) does not contain partition 1
        at org.apache.kafka.streams.processor.internals.ProcessorStateManager.register(ProcessorStateManager.java:185)
        at org.apache.kafka.streams.processor.internals.ProcessorContextImpl.register(ProcessorContextImpl.java:123)
        at org.apache.kafka.streams.state.internals.InMemoryKeyValueStoreSupplier$MemoryStore.init(InMemoryKeyValueStoreSupplier.java:102)
        at org.apache.kafka.streams.state.internals.InMemoryKeyValueLoggedStore.init(InMemoryKeyValueLoggedStore.java:56)
        at org.apache.kafka.streams.state.internals.MeteredKeyValueStore.init(MeteredKeyValueStore.java:85)
        at org.apache.kafka.streams.processor.internals.AbstractTask.initializeStateStores(AbstractTask.java:81)
        at org.apache.kafka.streams.processor.internals.StreamTask.<init>(StreamTask.java:119)
        at org.apache.kafka.streams.processor.internals.StreamThread.createStreamTask(StreamThread.java:633)
        at org.apache.kafka.streams.processor.internals.StreamThread.addStreamTasks(StreamThread.java:660)
        at org.apache.kafka.streams.processor.internals.StreamThread.access$100(StreamThread.java:69)
        at org.apache.kafka.streams.processor.internals.StreamThread$1.onPartitionsAssigned(StreamThread.java:124)
        at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.onJoinComplete(ConsumerCoordinator.java:228)
        at org.apache.kafka.clients.consumer.internals.AbstractCoordinator.joinGroupIfNeeded(AbstractCoordinator.java:313)
        at org.apache.kafka.clients.consumer.internals.AbstractCoordinator.ensureActiveGroup(AbstractCoordinator.java:277)
        at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.poll(ConsumerCoordinator.java:259)
        at org.apache.kafka.clients.consumer.KafkaConsumer.pollOnce(KafkaConsumer.java:1013)
        at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:979)
        at org.apache.kafka.streams.processor.internals.StreamThread.runLoop(StreamThread.java:407)

1 个答案:

答案 0 :(得分:6)

这是一个操作问题。 Kafka Streams不允许在“生命周期”期间更改输入主题分区的数量。

如果您停止正在运行的Kafka Streams应用程序,请更改输入主题分区的数量,然后重新启动应用程序它将中断(使用您在上面看到的错误)。为生产用例修复此问题很棘手,强烈建议更改输入主题分区的数量(参见下面的评论)。对于POC /演示,虽然不难解决。

为了解决这个问题,您应该使用Kafka的应用程序重置工具重置您的应用程序:

使用应用程序重置工具的缺点是您要清除整个应用程序状态。因此,为了使您的应用程序处于与以前相同的状态,您需要从头开始重新处理整个输入主题。这当然是唯一可行的,如果所有输入数据仍然可用,并且没有任何内容被应用主题保留时间/大小策略的代理删除。

此外,您应该注意,向输入主题添加分区会更改主题的分区架构(按键默认基于散列的分区)。因为Kafka Streams假定输入主题按键正确分区,如果使用重置工具并重新处理所有数据,则可能会得到错误的结果,因为“旧”数据的分区方式与“新”数据不同(即添加后的数据)新分区)。对于生产用例,您需要读取原始主题中的所有数据并将其写入新主题(分区数量增加)以正确分区数据(或者,当然,此步骤可能会更改不同记录的顺序密钥 - 通常不应该是一个问题 - 只是想提一下它。之后,您可以将新主题用作Streams应用程序的输入主题。

通过在阅读原始主题之后和执行任何实际处理之前直接使用运算符through("new_topic_with_more_partitions"),您可以在Streams应用程序中轻松完成此重新分区步骤。

但是,一般情况下,建议对生产用例的主题进行过度分区,以便以后永远不需要更改分区数。过度分区的开销相当小,以后会为您节省大量麻烦。如果您使用Kafka,这是一般性建议 - 它不仅限于Streams用例。

  

还有一句话:

     

有些人可能会建议手动增加Kafka Streams内部主题的分区数量。首先,这将是 hack ,并且由于某些原因不推荐

     
      
  1. 弄清楚正确的数字是多么棘手,因为它取决于各种因素(因为它是Stream的内部实现细节)。
  2.   
  3. 您还面临破坏分区方案的问题,如上段所述。因此,您的应用程序最有可能最终处于不一致状态。
  4.         

    为了避免应用程序状态不一致,Streams不会自动删除任何内部主题或更改内部主题的分区数,但会因您报告的错误消息而失败。这样可以确保用户通过手动执行“清理”来了解所有含义。

顺便说一下:对于即将推出的Kafka 0.10.2,此错误消息得到了改进:https://github.com/apache/kafka/blob/0.10.2/streams/src/main/java/org/apache/kafka/streams/processor/internals/InternalTopicManager.java#L100-L103

相关问题