如何在spark结构化流媒体中手动提交kafka偏移量?

时间:2018-06-13 19:01:06

标签: apache-spark apache-kafka spark-structured-streaming

我正在浏览Spark结构化流媒体 - Kafka集成指南here

在此链接中告知

  

enable.auto.commit:Kafka源代码不提交任何偏移量。

那么一旦我的spark应用程序成功处理了每条记录,我该如何手动提交偏移?

2 个答案:

答案 0 :(得分:7)

自Spark 3.0.0起

根据Structured Kafka Integration Guide,您可以将ConsumerGroup作为选项kafka.group.id提供:

val df = spark
  .readStream
  .format("kafka")
  .option("kafka.bootstrap.servers", "host1:port1,host2:port2")
  .option("subscribe", "topic1")
  .option("kafka.group.id", "myConsumerGroup")
  .load()

但是,Spark仍将不提交任何偏移量,因此您将无法“手动”向Kafka提交偏移量。此功能用于处理Kafka的最新功能Authorization using Role-Based Access Control,您的ConsumerGroup通常需要为此使用命名约定。

here讨论并解决了Spark 3.x应用程序的完整示例。

直到Spark 2.4.x

此功能似乎正在Spark社区中进行讨论 https://github.com/apache/spark/pull/24613

在该“拉取请求”中,您还将在https://github.com/HeartSaVioR/spark-sql-kafka-offset-committer处找到可能的解决方案。

目前,Spark结构化流+ Kafka集成documentation清楚地说明了它如何管理Kafka偏移。用于管理偏移量的最重要的Kafka配置为:

  • group.id::Kafka源将自动为每个查询创建唯一的组ID。根据{{​​3}},group.id将设置为
val uniqueGroupId = s"spark-kafka-source-${UUID.randomUUID}-${metadataPath.hashCode}"
  • auto.offset.reset::设置源选项startingOffsets以指定从何处开始。 结构化流技术管理哪些偏移量是在内部使用的,而不是依靠kafka消费者来实现。
  • enable.auto.commit: Kafka源代码没有任何偏移量。

因此,当前无法在结构化流中定义您的自定义group.id。Kafka使用者和结构化流将在内部管理偏移量,并且不会提交回Kafka(也不会自动)。

运行中的2.4.x

假设您有一个简单的Spark结构化流应用程序,它可以对Kafka进行读写,如下所示:

// create SparkSession
val spark = SparkSession.builder()
  .appName("ListenerTester")
  .master("local[*]")
  .getOrCreate()

// read from Kafka topic
val df = spark.readStream
  .format("kafka")
  .option("kafka.bootstrap.servers", "localhost:9092")
  .option("subscribe", "testingKafkaProducer")
  .option("failOnDataLoss", "false")
  .load()

// write to Kafka topic and set checkpoint directory for this stream
df.selectExpr("CAST(key AS STRING)", "CAST(value AS STRING)")
  .writeStream
  .format("kafka")
  .option("kafka.bootstrap.servers", "localhost:9092")
  .option("topic", "testingKafkaProducerOut")
  .option("checkpointLocation", "/home/.../sparkCheckpoint/")
  .start()

Spark的偏移量管理

提交此申请并处理数据后,可以在检查点目录中找到相应的偏移量:

myCheckpointDir /偏移量/

{"testingKafkaProducer":{"0":1}}

此处,检查点文件中的条目确认要使用的分区0的下一个偏移量是1。这意味着应用程序已经处理了名为0的主题的分区0的偏移量testingKafkaProducer

Spark code中提供了更多有关容错语义的信息。

卡夫卡的抵销管理

但是,如文档中所述,偏移量被提交回Kafka。 可以通过执行Kafka安装的kafka-consumer-groups.sh进行检查。

./ kafka / current / bin / kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group“ spark-kafka-source-92ea6f85-[...]-driver-0 “

TOPIC                PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG  CONSUMER-ID      HOST         CLIENT-ID
testingKafkaProducer 0          -               1               -    consumer-1-[...] /127.0.0.1   consumer-1

Kafka 不知道此应用程序的当前偏移量,因为它从未提交过。

可能的解决方案

我在网络上进行的一些研究发现,您可以在自定义的onQueryProgress Spark中使用StreamingQueryListener方法的回调函数来提交偏移量。

由于我不会声称自己已经发展了这一点,因此以下是帮助我理解的最重要的链接:

答案 1 :(得分:-1)

Spark检查点真的不可靠。强烈建议使用外部进程来存储偏移量,Zookeeper或HBase是替代方案。

使用外部存储,您将确保在提交之前完整处理您的记录。

在这个伟大的article中,您将找到有关如何使用Spark Streaming提交偏移的详细信息。