![](/img/trans.png)
[英]How to set specific offset number while consuming message from Kafka topic through Spark streaming Scala
[英]Spark Streaming from Kafka topic throws offset out of range with no option to restart the stream
我有一个在 Spark 2.1.1 上运行的流作业,轮询 Kafka 0.10。 我正在使用 Spark KafkaUtils类来创建 DStream,并且一切正常,直到我的数据由于保留策略而过期。 我的问题是当我停止工作以进行一些更改时,如果任何数据已超出主题范围,我会收到一条错误消息,指出我的偏移量超出范围。 我做了很多研究,包括查看 spark 源代码,我看到很多评论,比如这个问题中的评论: SPARK-19680 - 基本上是说数据不应该默默丢失 - 所以 auto.offset.reset 被忽略通过火花。 不过,我最大的问题是,我现在能做什么? 我的主题不会在 spark 中进行轮询 - 它在启动时因偏移异常而终止。 我不知道如何重置偏移量,所以我的工作将重新开始。 我没有启用检查点,因为我读到这些检查点对于这种用途是不可靠的。 我曾经有很多代码来管理偏移量,但是如果有任何提交,spark 似乎会忽略请求的偏移量,所以我目前正在管理这样的偏移量:
val stream = KafkaUtils.createDirectStream[String, T](
ssc,
PreferConsistent,
Subscribe[String, T](topics, kafkaParams))
stream.foreachRDD { (rdd, batchTime) =>
val offsets = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
Log.debug("processing new batch...")
val values = rdd.map(x => x.value())
val incomingFrame: Dataset[T] = SparkUtils.sparkSession.createDataset(values)(consumer.encoder()).persist
consumer.processDataset(incomingFrame, batchTime)
stream.asInstanceOf[CanCommitOffsets].commitAsync(offsets)
}
ssc.start()
ssc.awaitTermination()
作为一种解决方法,我一直在更改我的组 ID,但这真的很蹩脚。 我知道这是预期的行为,不应该发生,我只需要知道如何让流再次运行。 任何帮助,将不胜感激。
这是我编写的代码块,直到将真正的解决方案引入spark-streaming-kafka为止。 基本上,它会根据您设置的OffsetResetStrategy重置已过期的分区的偏移量。 只需给您提供给KafkaUtils的相同Map参数_params即可。 在从驱动程序调用KafkaUtils.create **** Stream()之前,请先调用此函数。
final OffsetResetStrategy offsetResetStrategy = OffsetResetStrategy.valueOf(_params.get(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG).toString().toUpperCase(Locale.ROOT));
if(OffsetResetStrategy.EARLIEST.equals(offsetResetStrategy) || OffsetResetStrategy.LATEST.equals(offsetResetStrategy)) {
LOG.info("Going to reset consumer offsets");
final KafkaConsumer<K,V> consumer = new KafkaConsumer<>(_params);
LOG.debug("Fetching current state");
final List<TopicPartition> parts = new LinkedList<>();
final Map<TopicPartition, OffsetAndMetadata> currentCommited = new HashMap<>();
for(String topic: this.topics()) {
List<PartitionInfo> info = consumer.partitionsFor(topic);
for(PartitionInfo i: info) {
final TopicPartition p = new TopicPartition(topic, i.partition());
final OffsetAndMetadata m = consumer.committed(p);
parts.add(p);
currentCommited.put(p, m);
}
}
final Map<TopicPartition, Long> begining = consumer.beginningOffsets(parts);
final Map<TopicPartition, Long> ending = consumer.endOffsets(parts);
LOG.debug("Finding what offsets need to be adjusted");
final Map<TopicPartition, OffsetAndMetadata> newCommit = new HashMap<>();
for(TopicPartition part: parts) {
final OffsetAndMetadata m = currentCommited.get(part);
final Long begin = begining.get(part);
final Long end = ending.get(part);
if(m == null || m.offset() < begin) {
LOG.info("Adjusting partition {}-{}; OffsetAndMeta={} Begining={} End={}", part.topic(), part.partition(), m, begin, end);
final OffsetAndMetadata newMeta;
if(OffsetResetStrategy.EARLIEST.equals(offsetResetStrategy)) {
newMeta = new OffsetAndMetadata(begin);
} else if(OffsetResetStrategy.LATEST.equals(offsetResetStrategy)) {
newMeta = new OffsetAndMetadata(end);
} else {
newMeta = null;
}
LOG.info("New offset to be {}", newMeta);
if(newMeta != null) {
newCommit.put(part, newMeta);
}
}
}
consumer.commitSync(newCommit);
consumer.close();
}
auto.offset.reset=latest/earliest
将仅在使用者第一次启动时应用。
有Spark JIRA可以解决此问题,在此之前,我们需要现场解决。 https://issues.apache.org/jira/browse/SPARK-19680
尝试
auto.offset.reset=latest
要么
auto.offset.reset=earliest
最早:将偏移量自动重置为最早的偏移量
最新:自动将偏移量重置为最新偏移量
none:如果未找到消费者组的先前偏移量,则向消费者抛出异常
其他:向消费者抛出异常。
影响保留值与最小和最大配置相对应的另一件事是日志保留策略。 假设您有一个保留时间配置为1小时的主题。 您产生10条消息,然后一个小时后又发布10条消息。 最大偏移量将保持不变,但最小偏移量将不能为0,因为Kafka将已删除这些消息,因此最小可用偏移量将为10。
通过包含“failOnDataLoss”=“false”,在流结构化结构中解决了这个问题。 目前还不清楚为什么 spark DStream 框架中没有这样的选项。
这是 Spark 开发人员的一个大问题!
在我们的项目中,我们试图通过重置 ealiest + 5 分钟的偏移量来解决这个问题……这在大多数情况下都有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.