我正在使用Kafka 0.8.2
从AdExchange接收数据,然后我使用Spark Streaming 1.4.1
将数据存储到MongoDB
。
我的问题是当我重新启动Spark Streaming
作业时,例如更新新版本,修复错误,添加新功能。它将继续阅读当前offset
的{{1}},然后在重新启动作业期间,我将丢失数据AdX推送到kafka。
我尝试类似kafka
的内容,但会收到0 - >最后,数据是巨大的,并在数据库中重复。
我也尝试将特定的auto.offset.reset -> smallest
和group.id
设置为consumer.id
,但它也一样。
如何保存Spark
或offset
消耗的最新zookeeper
点火,然后可以将其读回到最新的kafka
?
答案 0 :(得分:15)
createDirectStream函数的一个构造函数可以获取一个映射,该映射将分区id作为键,并将您开始使用的偏移量作为值。
在这里看看api:http://spark.apache.org/docs/2.2.0/api/java/org/apache/spark/streaming/kafka/KafkaUtils.html 我所谈论的地图通常称为:fromOffsets
您可以将数据插入地图:
startOffsetsMap.put(TopicAndPartition(topicName,partitionId), startOffset)
在创建直接流时使用它:
KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder, (String, String)](
streamingContext, kafkaParams, startOffsetsMap, messageHandler(_))
每次迭代后,您都可以使用以下方法获取已处理的偏移量:
rdd.asInstanceOf[HasOffsetRanges].offsetRanges
您将能够使用此数据在下一次迭代中构建fromOffsets映射。
您可以在此处查看完整的代码和用法:页面末尾的https://spark.apache.org/docs/latest/streaming-kafka-integration.html
答案 1 :(得分:2)
要添加到Michael Kopaniov的答案中,如果您真的想将ZK用作存储和加载偏移地图的地方,您可以。
但是,因为你的结果没有输出到ZK,所以除非你的输出操作是幂等的(听起来不是这样),否则你将无法获得可靠的语义。
如果可以将结果与mongo中的同一文档一起存储在单个原子动作中的偏移量中,那么对您来说可能更好。
答案 2 :(得分:1)
以下是一些可用于在ZK http://geeks.aretotally.in/spark-streaming-kafka-direct-api-store-offsets-in-zk/
中存储偏移量的代码当您调用KafkaUtils.createDirectStream时,可以使用以下代码来使用偏移量: http://geeks.aretotally.in/spark-streaming-direct-api-reusing-offset-from-zookeeper/
答案 3 :(得分:-1)
我还没有100%想到这一点,但最好的办法是设置JavaStreamingContext.checkpoint()。
有关示例,请参阅https://spark.apache.org/docs/1.3.0/streaming-programming-guide.html#checkpointing。
根据一些博客条目 https://github.com/koeninger/kafka-exactly-once/blob/master/blogpost.md ,有一些警告,但它几乎感觉它涉及某些仅仅提到并且没有实际解释的边缘情况。