繁体   English   中英

Spark Structured Streaming 中的 KafkaSource 的“偏移量已从 X 更改为 0”错误是什么?

[英]What is the “offset was changed from X to 0” error with a KafkaSource in Spark Structured Streaming?

我在带有检查点的 Spark 结构化流应用程序中使用 KafkaSource 收到错误“偏移量已从 X 更改为 0,某些数据可能已丢失”,但它似乎实际上并没有引起任何问题。 我试图弄清楚错误的实际含义。

我的设置如下。

  • 我在 docker 容器中运行了 Kafka (0.10.1.0),在 /tmp/kafka-logs 上安装了一个命名卷,以便在重新启动之间保留日志。

  • 我在另一个 docker 容器中有一个 Spark Structured Streaming (2.1.1) 应用程序。 这些流消耗来自 Kafka 的数据。 他们还在命名卷中再次安装的位置使用检查点,以确保在重新启动之间保留元数据。

  • 我使用一个实现ForeachWriter接口的自定义接收器,这意味着我必须实现我自己的处理版本日志,以便在一切重新启动时,我可以告诉 Spark Streaming 不要重新处理已经处理的内容。

所有这些都运行良好,数据从 Kafka 正确使用,我的自定义接收器正确处理它。

现在如果我杀掉Spark Streaming应用,让Kafka中的数据堆积起来,然后重启Spark Streaming,就会抛出如下错误,说明Kafka中的一些数据已经不可用了

ERROR StreamExecution: Query [id = cd2b69e1-2f24-439a-bebc-89e343df83a8, runId = d4b3ae65-8cfa-4713-912c-404623710048] terminated with error

Java.lang.IllegalStateException: Partition input.clientes-0's offset
 was changed from 908 to 0, some data may have been missed.

Some data may have been lost because they are not available in Kafka
 any more; either the data was aged out by Kafka or the topic may have 
 been deleted before all the data in the topic was processed. If you 
 don't want your streaming query to fail on such cases, set the source 
 option "failOnDataLoss" to "false".

at org.apache.spark.sql.kafka010.KafkaSource.org$apache$spark$sql$kafka010$KafkaSource$$reportDataLoss(KafkaSource.scala:329)
at org.apache.spark.sql.kafka010.KafkaSource$$anonfun$8.apply(KafkaSource.scala:283)
at org.apache.spark.sql.kafka010.KafkaSource$$anonfun$8.apply(KafkaSource.scala:281)
at scala.collection.TraversableLike$$anonfun$filterImpl$1.apply(TraversableLike.scala:248)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
at scala.collection.TraversableLike$class.filterImpl(TraversableLike.scala:247)
at scala.collection.TraversableLike$class.filter(TraversableLike.scala:259)
at scala.collection.AbstractTraversable.filter(Traversable.scala:104)
at org.apache.spark.sql.kafka010.KafkaSource.getBatch(KafkaSource.scala:281)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatch$2$$anonfun$apply$6.apply(StreamExecution.scala:452)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatch$2$$anonfun$apply$6.apply(StreamExecution.scala:448)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
at scala.collection.Iterator$class.foreach(Iterator.scala:893)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1336)
at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
at org.apache.spark.sql.execution.streaming.StreamProgress.foreach(StreamProgress.scala:25)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:241)
at org.apache.spark.sql.execution.streaming.StreamProgress.flatMap(StreamProgress.scala:25)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatch$2.apply(StreamExecution.scala:448)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatch$2.apply(StreamExecution.scala:448)
at org.apache.spark.sql.execution.streaming.ProgressReporter$class.reportTimeTaken(ProgressReporter.scala:262)
at org.apache.spark.sql.execution.streaming.StreamExecution.reportTimeTaken(StreamExecution.scala:46)
at org.apache.spark.sql.execution.streaming.StreamExecution.org$apache$spark$sql$execution$streaming$StreamExecution$$runBatch(StreamExecution.scala:447)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatches$1$$anonfun$1.apply$mcV$sp(StreamExecution.scala:255)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatches$1$$anonfun$1.apply(StreamExecution.scala:244)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatches$1$$anonfun$1.apply(StreamExecution.scala:244)
at org.apache.spark.sql.execution.streaming.ProgressReporter$class.reportTimeTaken(ProgressReporter.scala:262)
at org.apache.spark.sql.execution.streaming.StreamExecution.reportTimeTaken(StreamExecution.scala:46)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anonfun$org$apache$spark$sql$execution$streaming$StreamExecution$$runBatches$1.apply$mcZ$sp(StreamExecution.scala:244)
at org.apache.spark.sql.execution.streaming.ProcessingTimeExecutor.execute(TriggerExecutor.scala:43)
at org.apache.spark.sql.execution.streaming.StreamExecution.org$apache$spark$sql$execution$streaming$StreamExecution$$runBatches(StreamExecution.scala:239)
at org.apache.spark.sql.execution.streaming.StreamExecution$$anon$1.run(StreamExecution.scala:177)

但是在抛出错误后,我看到我的流正常启动。 Spark Streaming 使用预期的版本正确地将堆积在 Kafka 中的数据推送到我的自定义接收器。 然后我的接收器继续并正确处理新数据。

所以错误表明某些数据在 Kafka 中不再可用,但它仍然设法被 Spark Streaming 正确使用。

如果我在没有数据推送到 Kafka 的情况下重新启动 Spark Streaming 应用程序,我会再次收到相同的错误。 如果我开始向 Kafka 推送新数据,系统将继续对其进行正确处理。

有人知道这里会发生什么吗? 我是否错误地解释了错误?

/tmp/kafka-logs是 Kafka 的日志目录,其中存储了所有偏移量、主题信息。 如果已损坏,或者有些数据被删除,您需要设置的选项failOnDataLoss:false在你的卡夫卡选项SparkProcessContext并重新启动星火工作。

Option  : failOnDataLoss
Value   : true or false
Default : TRUE

含义:当数据可能丢失(例如,主题被删除,或偏移量超出范围)时是否使查询失败。 这可能是误报。 当它没有按预期工作时,您可以禁用它。

这似乎是旧版本的 kafka-clients 库中的一个已知错误。

SPARK-26267的描述说

“由于KAFKA-7703- KafkaConsumer.position 可能会在调用“seekToEnd”后返回错误的偏移量,当Kafka 源尝试获取最新的偏移量时,它可能会获取最早的偏移量,然后它会重新处理已处理的消息当它在下一批中获得正确的最新偏移量时。”

总而言之,引用参与其中的开发人员的话:

“这是 Kafka 中的一个已知问题,请参阅 KAFKA-7703。这在 SPARK-26267 中的 2.4.1 和 3.0.0 中已修复。请将 Spark 升级到更高版本。另一种可能性是将 Kafka 升级到 2.3.0,其中卡夫卡那边是固定的。”

“KAFKA-7703 仅存在于 Kafka 1.1.0 及更高版本中,因此可能的解决方法是使用没有此问题的旧版本。这不会影响 Spark 2.3.x 及更低版本,因为我们使用 Kafka 0.10.0.1默认。”

在我们的案例中,我们在 HDP 3.1 平台上遇到了同样的问题。 我们有 Spark 2.3.2 和 spark-sql-kafka 库( https://mvnrepository.com/artifact/org.apache.spark/spark-sql-kafka-0-10_2.11/2.3.2.3.1.0。 0-78 ),但是,使用 kafka-clients 2.0.0。 这意味着我们由于后续条件而面临此错误:

  • 我们的火花 < 2.4.1
  • 1.1.0 < 我们的卡夫卡 < 2.3.0

可能的解决方案

我们能够通过删除包含0偏移量的批次号的“偏移量”子文件夹中的检查点文件来“解决”这个问题。

删除此文件时,请确保删除后“commits”和“offset”子文件夹中检查点文件中的批号仍然匹配。

这远不是一个理想的解决方案,尤其是对于生产环境。 但是,如果您无法轻松更新库,它可能会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM