Spark Streaming Kafka中的DStream过滤和偏移管理

时间:2017-10-31 15:50:08

标签: scala apache-kafka spark-streaming

我目前正在编写一个Spark流式应用程序,它从Kafka读取数据并在应用某些转换之前尝试对其进行解码。

当前的代码结构如下所示:

val stream = KafkaUtils.createDirectStream[String, String](...)
 .map(record => decode(record.value())
 .filter(...)
 .foreachRDD { rdd =>
   val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
   ...
   stream.asInstanceOf[CanCommitOffsets].commitAsync(offsetRanges)
 }

故障的解码和过滤发生在DStream上,偏移管理在foreachRDD内完成,这意味着我只会提交成功的记录。

要提交失败的记录,我可以移动foreachRDD循环中的所有内容:

val stream = KafkaUtils.createDirectStream[String, String](...)
 .foreachRDD { rdd =>
   val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
   ...
   // Decoding and filtering here
   ...
   stream.asInstanceOf[CanCommitOffsets].commitAsync(offsetRanges)
 }

但是,我想知道是否有另一种提交失败记录的方法。也许不提交失败的记录是可以接受的吗?

1 个答案:

答案 0 :(得分:0)

我假设您正在使用spark-streaming-kafka库。

阅读offset Ranges的文档,它存储了与主题分区的偏移量的范围。它不会根据客户端过滤“ .filter(…)”动作过滤或标记该范围内的单个偏移量。因此,如果您提交该offsetRanges,则无论过滤器操作如何,它都会为每个分区提交最高的偏移量。

这很有意义,因为您的消费者正在告诉Kafka经纪人,或更准确地说,Group Coordinator告诉他们它消耗了这些消息。协调员对您对数据的实际用途不感兴趣,它只是想知道特定的消费者组是否正在读取消息/偏移量。

回到您的问题...

我想知道是否还有另一种方法来提交失败的记录。

尽管看起来好像不需要它,但是是的,还有另一种提交“失败”记录的方法。您可以enable auto commit。连同使用者配置auto.commit.interval.ms,您可以定期提交从主题中轮询的使用者偏移量。

不提交失败的记录是否可以接受?

我不了解您的特定用例,但是不提交失败的记录也是可以接受的。如上所述,组协调员对消费者消耗的每个分区的最高偏移量感兴趣。如果您使用一个包含10条消息的主题,那么您将从头开始阅读,并且只提交第9个偏移量(偏移量计数从0开始),那么下次您启动消费者时,它将忽略前十条消息。

您可以查看Kafka内部主题__consumer_offsets来查看每个消费者组存储的内容:主题,分区,偏移量(…等)。