我想知道Flink窗口是否有可能导致从数据进入管道直到将其写入Cassandra中的表时延迟10分钟。
我的初衷是将每个事务写入Cassandra中的表并使用Web层的范围键查询表,但由于数据量的原因,我正在寻找延迟写入N秒的选项。这意味着我的表只能拥有至少10分钟的数据。
下面的小图显示了每分钟滚动的10分钟窗口。随着时间的推移,我只想将数据写入超过10分钟的Cassandra(绿色部分)。我想这对Flink来说甚至可能吗?
我可以创建每分钟滚动11分钟的窗口,但我最终会丢掉90%的数据,这似乎是浪费。
最终解决方案
我创建了自己的FlinkKafkaConsumer09
名为DelayedKafkaConsumer
的主题,其主要原因是覆盖了KafkaFetcher
的创建
public class DelayedKafkaConsumer<T> extends FlinkKafkaConsumer09<T> {
private ConsumerRecordFunction applyDelayAction;
.............
@Override
protected AbstractFetcher<T, ?> createFetcher(SourceContext<T> sourceContext, Map<KafkaTopicPartition, Long> assignedPartitionsWithInitialOffsets,
SerializedValue<AssignerWithPeriodicWatermarks<T>> watermarksPeriodic,
SerializedValue<AssignerWithPunctuatedWatermarks<T>> watermarksPunctuated,
StreamingRuntimeContext runtimeContext, OffsetCommitMode offsetCommitMode) throws Exception {
return new DelayedKafkaFetcher<>(
sourceContext, assignedPartitionsWithInitialOffsets, watermarksPeriodic, watermarksPunctuated,
runtimeContext.getProcessingTimeService(), runtimeContext.getExecutionConfig().getAutoWatermarkInterval(),
runtimeContext.getUserCodeClassLoader(), runtimeContext.getTaskNameWithSubtasks(),
runtimeContext.getMetricGroup(), this.deserializer, this.properties, this.pollTimeout, useMetrics, applyDelayAction);
}
DelayedKafkaFetcher
在其runFetchLoop
中有一小段代码,在发出记录之前会休眠n毫秒。
private void delayMessage(Long msgTransactTime, Long nowMinusDelay) throws InterruptedException {
if (msgTransactTime > nowMinusDelay) {
Long sleepTimeout = msgTransactTime - nowMinusDelay;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(format("Message with transaction time {0}ms is not older than {1}ms. Sleeping for {2}", msgTransactTime, nowMinusDelay, sleepTimeout));
}
TimeUnit.MILLISECONDS.sleep(sleepTimeout);
}
}