flink cep

cep是flink为了从流中提取具有某种特征的复杂事件,所提供的一个包,这两天研究了一下,写个非常有意思的小例子来学习一下。

@Test
public void testEventTimeWithWindow() throws Exception {
    StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
    env.setParallelism(1);

    // f0是名字,f1是事件时间
    DataStream<Tuple2<String, Long>> input = env.fromElements(
            Tuple2.of("alice", 0L),
            Tuple2.of("bob", 2L),
            Tuple2.of("tom", 10L),
            Tuple2.of("luna", 4L),
            Tuple2.of("luck", 15L),
            Tuple2.of("rice", 50L));

    // 设置事件时间和watermark
    DataStream<String> inputWithEventTime = input.assignTimestampsAndWatermarks(
            new AssignerWithPunctuatedWatermarks<Tuple2<String, Long>>() {
                @Override
                public long extractTimestamp(
                        Tuple2<String, Long> element,
                        long recordTimestamp) {
                    return element.f1;
                }

				// watermark设置为5ms
                @Override
                public Watermark checkAndGetNextWatermark(
                        Tuple2<String, Long> lastElement,
                        long extractedTimestamp) {
                    return new Watermark(lastElement.f1 - 5);
                }
            }
    )
            .map((MapFunction<Tuple2<String, Long>, String>) value -> value.f0);

    // 设置cep复杂事件模式,我们想找到5ms之内连续发生的事件
    Pattern pattern = Pattern
            .begin("first")
            .followedByAny("second")
            .within(Time.milliseconds(5));

    // 在流中使用pattern进行发现
    DataStream<String> result = CEP.pattern(inputWithEventTime, pattern)
            .inEventTime()
            .select((PatternSelectFunction<Tuple2<String, Long>, String>) pattern1 ->
                    String.format("first element: %s, second element: %s",
                            pattern1.get("first").get(0), pattern1.get("second").get(0))
            );

    result.print();
    env.execute();
}

如上面的代码所示,事件时间的顺序是:

nameevent time
alice0ms
bob2ms
luna4ms
tom10ms
luck15ms
rice50ms

因为上面的代码可以找出5ms内连续发生的事件,所以我一开始以为上面的代码的输出会是:

first element: alice, second element: bob
first element: bob, second element: luna

然而结果却是:

first element: alice, second element: bob

这是为啥呢?


后来发现,这是因为设置了5ms的watermark,因为流中元素(10ms,tom)来到之后,watermark就已经被推进到了
当 前 事 件 事 件 ( 10 m s ) − 等 待 时 间 ( 5 m s ) = w a t e r m a r k ( 5 m s ) 当前事件事件(10ms)-等待时间(5ms)=watermark(5ms) (10ms)(5ms)=watermark(5ms)
因此当前watermark已经被推进到了5ms,所有当元素(4ms, luna)来了之后,不会触发事件识别。

为了验证我的想法,我把input改为:

DataStream<Tuple2<String, Long>> input = env.fromElements(
        Tuple2.of("alice", 0L),
        Tuple2.of("bob", 2L),
        Tuple2.of("tom", 10L),
        Tuple2.of("luna", 6L),
        Tuple2.of("luck", 15L),
        Tuple2.of("rice", 50L));

将luna这一条事件事件改为6ms,比5ms的watermark要迟,因此还能够触发cep识别,这时候输出的结果就变成了:

first element: alice, second element: bob
first element: bob, second element: luna
first element: luna, second element: tom
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canaryW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值