我想为Apache flink中的事件创建一个事件时钟。我正在按照以下方式
public class TimeStampAssigner implements AssignerWithPeriodicWatermarks<Tuple2<String, String>> {
private final long maxOutOfOrderness = 0; // 3.5
private long currentMaxTimestamp;
@Override
public long extractTimestamp(Tuple2<String, String> element, long previousElementTimestamp) {
currentMaxTimestamp = new Date().getTime();
return currentMaxTimestamp;
}
@Override
public Watermark getCurrentWatermark() {
return new Watermark(currentMaxTimestamp - maxOutOfOrderness);
}
}
请检查上面的代码,并告诉我我是否正确执行了操作。在分配了事件时间和水印之后,我要在处理功能中处理流,在该功能中,我将针对不同的键收集流数据10分钟。
答案 0 :(得分:1)
否,这不是适当的实现。事件时间时间戳应该是确定性的(即可重现的),并且应基于事件流中的数据。相反,如果要使用Date()。getTime,则或多或少地使用处理时间。
通常,在进行事件时间处理时,您的事件将具有一个timestamp字段,并且timestamp提取器将返回该字段的值。
您展示的实现将失去处理事件时间所带来的大部分好处,例如重新处理历史数据以重现历史结果的能力。
答案 1 :(得分:0)
您的实现正在实现Flink系统的获取时间,而不是事件时间。例如,如果您从Kafka消费,则 previousElementTimestamp 通常应指向向Kafka产生事件的时间(如果Kafka生产者没有其他说明),这将使您的流式处理可复制的。
如果要在Flink中实现事件时间处理,则应该使用一些与元素关联的时间戳。可以是元素本身,也可以在元素本身内部(这对时间序列有意义),也可以存储在Kafka中,并在 previousElementTimestamp 下可用。
关于 maxOutOfOrderness ,您可能还想考虑Flink的side output功能,该功能可以在创建窗口后获取后期元素并更新Flink作业的输出。
如果您从Kafka消费,并且想通过一些数据丢失事件来简化时间处理实现,请使用AscendingTimestampExtractor。 AscendingTimestampExtractor可能会出现一些潜在问题,以防您未在分区内对数据进行排序或在操作员之后而不是在KafkaSource之后直接应用此提取器。 对于健壮的工业用例,您应该按照Google DataFlow model所述,在持久日志存储中实施水印提取。