Flink TimeStamp,在流中添加计算字段

时间:2016-09-14 14:50:43

标签: java apache-flink flink-streaming

我有一个无序的流,我需要对它们进行排序,并在下一帧中使用相同的字段对字段值求和。我的代码:

env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
DataStream<Message> messageswithTS = messages.assignTimestampsAndWatermarks(new TimeLagWaterMarkGenerator());
DataStream<Message> SumNumber = messageswithTS 
            .keyBy("deviceId")
            .map(new Sumalo())

其中Sumalo()是添加的函数。提取TimeStamps的代码:

public class TimeLagWaterMarkGenerator implements AssignerWithPeriodicWatermarks<Message> {

private static final long serialVersionUID = 1L;
private long currentMaxTimestamp;

@Override
public long extractTimestamp(Message element, long previousElementTimestamp) {
    long timestamp = element.getDate();
    currentMaxTimestamp = Math.max(timestamp, currentMaxTimestamp);
    return timestamp;
}

@Override
public Watermark getCurrentWatermark() {
    return new Watermark(currentMaxTimestamp);
}
}

结果:

1   TRUE    0   21  1473861657491   6af7ecfb-5122-48b6-ada1-0ea39d1d4740
1   FALSE   3   3   1473861657496   c8b4617d-534b-4c5e-825c-a8c5556fcd87
1   TRUE    1   29  1473861657497   f5b72056-ec3d-4c97-b86d-73ed728757c3
1   FALSE   0   29  1473861657501   363d061d-ce02-4709-9683-b3bb233861f3
....

正确的结果:

1   TRUE    0   0   1473861657491   6af7ecfb-5122-48b6-ada1-0ea39d1d4740
1   FALSE   3   3   1473861657496   c8b4617d-534b-4c5e-825c-a8c5556fcd87
1   TRUE    1   4   1473861657497   f5b72056-ec3d-4c97-b86d-73ed728757c3
1   FALSE   0   4   1473861657501   363d061d-ce02-4709-9683-b3bb233861f3
....

感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

Flink 在事件时间自动对事件时间流进行排序,并且也提供操作员对事件时间流进行排序(这只能是可能的)在事件时间,即,将无序流转换为有序流)。

但是,您可以通过扩展AbstractStreamOperator来自行实现此类运算符。这是一个低级接口,您可以在其中访问事件,分配的时间戳和接收的水印。操作员可以如下工作。它可以将所有到达的元素插入到按事件时间排序的堆中。当水印到达时,它会发出时间戳小于水印的所有元素。如果后期元素到达(即,时间戳小于当前水印的元素),您可以发出它(破坏流的完整顺序)或丢弃它。操作员还需要通过将堆保持为Flink管理状态来参与检查点。您应该知道这个界面非常低级,需要很好地理解Flink的工作原理。此外,它可能会在次要版本之间发生变化。

关于您的时间戳和水印分配器,您不会为水印添加任何松弛。通过此实现,您可能会有许多后期元素。看看BoundedOutOfOrdernessTimestampExtractor

答案 1 :(得分:0)

正如前面的答案已经指出的那样,您需要在流的转换操作中创建一个自定义运算符。我发现this链接对于解决我所追求的类似问题非常有用。