使用OFFSET在KAFKA中恢复丢失的消息

时间:2016-10-11 17:16:27

标签: apache-kafka spark-streaming

我在接受采访时被问过这个问题。

想象一下,由于失败而导致数据包丢失(不确定其消费者失败或经纪人)。应该做什么(代码实现)在此期间使用偏移恢复丢失的消息?

对不起,我的问题可能不太清楚,因为问的方式类似。

感谢

3 个答案:

答案 0 :(得分:1)

如果您知道要恢复的邮件的偏移量以及它属于哪个分区,则可以使用KafkaConsumer方法seek

consumer.seek(new TopicPartition("topic-name", partNumber), offsetNumber);

详细here

下一次调用poll()会在列表中首先显示您错过的消息。

这只适用于您首先自行管理抵消的情况。如果您让Kafka管理偏移量,您可能不知道偏移数量,并且您可能最终会消耗两次消息(对poll()的调用将从最后提交的偏移开始消耗) )。

答案 1 :(得分:0)

Kafka遵循at-least once消息传递语义,这意味着您可能在代理失败时获得重复,您不会丢失数据。

但是当你创建Kafka Producer如果你有这个属性为0,那么它将尝试只发送一次,即使在代理失败的情况下它也不会尝试重新发送。因此,如果代理失败,您可能会丢失数据。

props.put("retries", 0);

因此,您可以将此属性值更改为1,因此它将尝试再次发送,同时{Zoo}会自动在Zookeeper中管理,如果消息仅成功传递,它将更新{{1}中的偏移量}}

此外,由于您提到要使用SPark Streaming,因此SPark Streaming支持两种不同的方法。

<强> 1。基于接收者: 偏移量在Zookeeper中处理。

<强> 2。直接方法: 在存储消息的本地处理偏移量,这种方法也支持Exactly-once消息传递。

有关详细信息,请查看此link

答案 2 :(得分:0)

阅读了很多文章和文档后,我觉得最好的答案可能是:

使用没有接收器的新Spark Kafka Consumer(spark-streaming-kafka-0-10_2.11)。在这种方法中,我们可以从我们想要阅读的地方提供startOffset。

  

val offsetRanges = Array(// topic,partition,inclusive起始   偏移,独占结束偏移OffsetRange(“test”,0,0,100),
  OffsetRange(“test”,1,0,100))

     

val rdd = KafkaUtils.createDirectStream [String,String](sparkContext,   kafkaParams,offsetRanges,PreferConsistent)

阅读并处理完您的消息后,获取您阅读的偏移量并将其存储在Kafka或Zk或外部交易数据库中。

  

offsetRanges = rdd.asInstanceOf [HasOffsetRanges] .offsetRanges

每次我们正在启动Job时,从数据库中获取Offsets并将其传递给createDirectStream以获得exacly once机制。

更多阅读 http://blog.cloudera.com/blog/2015/03/exactly-once-spark-streaming-from-apache-kafka/ https://spark.apache.org/docs/latest/streaming-kafka-0-10-integration.html