Apache Flink:KafkaProducer数据丢失

时间:2017-02-02 20:52:24

标签: apache-kafka apache-flink producer

我们的Flink流式工作流程向Kafka发布消息。在将消息添加到其内部缓冲区之前,KafkaProducer的“重试”机制不会启动。

如果在此之前有异常,KafkaProducer将抛出该异常,并且似乎Flink没有处理它。在这种情况下,将会有数据丢失。

相关Flink代码(FlinkKafkaProducerBase):

if (logFailuresOnly) {
            callback = new Callback() {
                @Override
                public void onCompletion(RecordMetadata metadata, Exception e) {
                    if (e != null) {
                        LOG.error("Error while sending record to Kafka: " + e.getMessage(), e);
                    }
                    acknowledgeMessage();
                }
            };
        }
        else {
            callback = new Callback() {
                @Override
                public void onCompletion(RecordMetadata metadata, Exception exception) {
                    if (exception != null && asyncException == null) {
                        asyncException = exception;
                    }
                    acknowledgeMessage();
                }
            };
        }

以下是我们发现会导致数据丢失的情况:

  1. 所有kafka经纪人都倒闭了。

    在这种情况下,在向其缓冲区附加消息之前,KafkaProducer会尝试获取元数据。如果KafkaProducer无法在配置的超时中获取元数据,则会引发异常。

  2. - 内存记录不可写(kafka 0.9.0.1库中的现有错误)

  3. https://issues.apache.org/jira/browse/KAFKA-3594

    在上述两种情况下,KafkaProducer都不会重试,Flink会忽略这些消息。消息甚至没有记录。例外情况是,但不是失败的消息。

    可能的解决方法(Kafka设置):

    1. 元数据超时值非常高(metadata.fetch.timeout.ms)
    2. 缓冲区到期的非常高的值(request.timeout.ms)
    3. 我们仍在调查更改上述kafka设置可能产生的副作用。

      那么,我们的理解是否正确?或者有没有办法通过修改一些Flink设置来避免这种数据丢失?

      感谢。

1 个答案:

答案 0 :(得分:0)

以下是我在想你的问题。 首先参见Kafka保证之一:

  

对于复制因子为N的主题,我们将容忍最多N-1个服务器故障,而不会丢失任何记录提交到日志

首先,它关心提交给日志的消息或记录。任何未能交付的记录都不会被视为已提交。其次,如果所有经纪人都倒闭了,那么会有一些数据丢失。

以下设置是我们用来防止生产者方面数据丢失的原因:

  • block.on.buffer.full = true
  • acks = all
  • retries = MAX_VALUE
  • max.in.flight.requests.per.connection = 1
  • 使用KafkaProducer.send(记录,回调)代替send(记录)
  • unclean.leader.election.enable =假
  • replication.factor> min.insync.replicas
  • min.insync.replicas> 1