在线为kafka添加分区或代理是否安全?

时间:2016-03-20 13:20:26

标签: apache-kafka kafka-consumer-api kafka-producer-api

感谢您的耐心等待。

  1. 在线上向主题添加分区后,kafka使用者停止阅读消息,并且不会抛出任何异常。消费者只是阻止。每次我们都要重启消费者。我认为这是不合理的,我找不到任何关于它的文档。
  2. 此外,处理消息中发生错误时,消费者线程不会恢复。我们的消费者读取消息并将其插入MySql。一旦网络出现故障,消费者无法连接到MySql,然后阻止并停止阅读消息,直到我们重新启动它。

    1. 添加分区时旧数据和新数据会发生什么变化? 文档(https://kafka.apache.org/documentation.html#basic_ops_modify_topic)说:
    2. “请注意,分区的一个用例是对数据进行语义分区,并且添加分区不会更改现有数据的分区,因此如果依赖于该分区,这可能会干扰消费者。即,如果数据通过哈希进行分区(键)%number_of_partitions然后这个分区可能会通过添加分区进行洗牌,但Kafka不会尝试以任何方式自动重新分配数据。“

      “不尝试自动重新分发数据”是什么意思?旧数据未更改,新数据将不会发送到添加的分区?

      1. 当经纪人关闭时,kafka制作人无法发送消息。
      2. 我们有一个包含3个分区和2个副本的主题。 kafka集群有3个经纪人。但是当经纪人倒闭时,会发生异常:

        kafka.producer.async.ProducerSendThread.error():103: - Error in handling batch of 65 events
        kafka.common.FailedToSendMessageException: Failed to send messages after 3 tries.
          at kafka.producer.async.DefaultEventHandler.handle(DefaultEventHandler.scala:90) ~[kafka_2.9.2-0.8.2.0.jar:na]
         at kafka.producer.async.ProducerSendThread.tryToHandle(ProducerSendThread.scala:105) [kafka_2.9.2-0.8.2.0.jar:na]
             at kafka.producer.async.ProducerSendThread$$anonfun$processEvents$3.apply(ProducerSendThread.scala:88) [kafka_2.9.2-0.8.2.0.jar:na]
               at kafka.producer.async.ProducerSendThread$$anonfun$processEvents$3.apply(ProducerSendThread.scala:68) [kafka_2.9.2-0.8.2.0.jar:na]
         at scala.collection.immutable.Stream.foreach(Stream.scala:526) [scala-library-2.9.2.jar:na]
           at kafka.producer.async.ProducerSendThread.processEvents(ProducerSendThread.scala:67) [kafka_2.9.2-0.8.2.0.jar:na]
              at kafka.producer.async.ProducerSendThread.run(ProducerSendThread.scala:45) [kafka_2.9.2-0.8.2.0.jar:na]
        
        kafka.producer.async.DefaultEventHandler.error():97: - Failed to send requests for topics risk_acts with correlation ids in [433266,433395]
        

        添加新经纪商时也会出现同样的问题。我们必须在生产者的“metadata.broker.list”配置中添加新的代理主机名和端口,然后重新启动它。

        我们正在使用高级api,而kafka的版本是:

        <dependency>
              <groupId> org.apache.kafka</groupId >
              <artifactId> kafka_2.9.2</artifactId >
              <version> 0.8.2.0</version >
        </dependency>
        

        生产者配置:

        <entry key="metadata.broker.list" value="${metadata.broker.list}" />
        <entry key="serializer.class" value="kafka.serializer.StringEncoder" />
        <entry key="key.serializer.class" value="kafka.serializer.StringEncoder" />
        <entry key="request.required.acks" value="-1" />
        <entry key="producer.type" value="async" />
        <entry key="queue.enqueue.timeout.ms" value="-1" />
        <entry key="compression.codec" value="1" />
        

        消费者配置:

        <entry key="zookeeper.connect" value="${zookeeper.connect}" />
        <entry key="group.id" value="${kafka.consumer.group.id}" />
        <entry key="zookeeper.session.timeout.ms" value="40000" />
        <entry key="rebalance.backoff.ms" value="10000" />
        <entry key="zookeeper.sync.time.ms" value="2000" />
        <entry key="auto.commit.interval.ms" value="1000" />
        <entry key="auto.offset.reset" value="smallest" />
        

        生产者代码和消费者代码如下: https://cwiki.apache.org/confluence/display/KAFKA/0.8.0+Producer+Example https://cwiki.apache.org/confluence/display/KAFKA/Consumer+Group+Example

2 个答案:

答案 0 :(得分:0)

对于#2,请说keyLong。假设你有10个分区。在分区中分发Long的一种方法是简单地执行模数运算key % num_partitions。但现在想想添加分区时会发生什么。根据{{​​1}}的当前值,已写入的消息将位于错误的分区中。这就是说Kafka不会自动为你重新划分任何东西。

答案 1 :(得分:0)

首先,我需要您了解添加分区重新分区之间的区别。

如果要进行重新分区:现有数据将从一个分区移至另一个分区

添加额外的分区时:旧数据将保持不变,而新数据将在所有分区中进行分发。

在这两种情况下,组协调器都会使用新的分区列表将信号发送给所有消费者,然后消费者将重新平衡并最终连接到所有请愿书。

对于您而言,您可能会遇到其他与增加分区无关的问题。

可能在服务器上启用调试日志,您将看到其他详细信息