有没有办法从Spark流作业读取Kafka流中的特定偏移量?

时间:2019-04-24 10:50:18

标签: java apache-kafka spark-streaming

我正在尝试使用以下操作将我的Spark流作业的偏移量提交给Kafka:

OffsetRange[] offsetRanges = ((HasOffsetRanges) rdd.rdd()).offsetRanges();

            // some time later, after outputs have completed
              ((CanCommitOffsets) stream.inputDStream()).commitAsync(offsetRanges);

我从这个问题中得到了

Spark DStream from Kafka always starts at beginning

这工作正常,正在提交偏移量。但是,问题在于这是异步的,这意味着即使在该行中发送了两次以上的偏移提交之后,Kafka仍可能会保留之前两次提交的偏移。如果此时消费者崩溃了,我将其重新备份,它将开始读取已经处理的消息。

现在,来自其他来源,例如此处的评论部分:

https://dzone.com/articles/kafka-clients-at-most-once-at-least-once-exactly-o

我了解到,无法从Spark流作业同步提交偏移量(尽管如果使用Kafka流,则有一种方法)。人们宁愿建议将偏移量保留在数据库中,以便将计算的最终结果持久存储在流中。

现在,我的问题是: 如果我确实将当前读取的偏移量存储在数据库中,那么下次如何从该偏移量开始读取流?

1 个答案:

答案 0 :(得分:0)

我研究并找到了问题的答案,所以我将其发布在这里给其他可能遇到相同问题的人:

  • 使用org.apache.kafka.common.TopicPartition作为键,并使用Long作为值来制作Map对象。 TopicPartition构造函数采用两个参数,主题名称和您将从中读取的分区。 Map对象的值是您要从中读取流的偏移量的长表示形式。

    Map startingOffset = new HashMap <>();     startingOffset.put(new TopicPartition(“ topic_name”,0),3332980L);

  • 将流内容读取到适当的JavaInputStream中,并将先前创建的Map对象提供为ConsumerStrategies.Subscribe()方法的参数。

    final JavaInputDStream>流= KafkaUtils.createDirectStream(jssc,                     LocationStrategies.PreferConsistent(),ConsumerStrategies.Subscribe(topics,kafkaParams,startingOffset));