我们的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();
}
};
}
以下是我们发现会导致数据丢失的情况:
所有kafka经纪人都倒闭了。
在这种情况下,在向其缓冲区附加消息之前,KafkaProducer会尝试获取元数据。如果KafkaProducer无法在配置的超时中获取元数据,则会引发异常。
- 内存记录不可写(kafka 0.9.0.1库中的现有错误)
https://issues.apache.org/jira/browse/KAFKA-3594
在上述两种情况下,KafkaProducer都不会重试,Flink会忽略这些消息。消息甚至没有记录。例外情况是,但不是失败的消息。
可能的解决方法(Kafka设置):
我们仍在调查更改上述kafka设置可能产生的副作用。
那么,我们的理解是否正确?或者有没有办法通过修改一些Flink设置来避免这种数据丢失?
感谢。
答案 0 :(得分:0)
以下是我在想你的问题。 首先参见Kafka保证之一:
对于复制因子为N的主题,我们将容忍最多N-1个服务器故障,而不会丢失任何记录提交到日志。
首先,它关心提交给日志的消息或记录。任何未能交付的记录都不会被视为已提交。其次,如果所有经纪人都倒闭了,那么会有一些数据丢失。
以下设置是我们用来防止生产者方面数据丢失的原因: