我正在尝试使用以下操作将我的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流,则有一种方法)。人们宁愿建议将偏移量保留在数据库中,以便将计算的最终结果持久存储在流中。
现在,我的问题是: 如果我确实将当前读取的偏移量存储在数据库中,那么下次如何从该偏移量开始读取流?
答案 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));