51、Flink 窗口 Join 之滑动窗口事件时间 Join 代码示例

1、概述

窗口中的水位线取的是两条流中的最小值;

一个流中的元素如果没有与另一个流中的元素组合起来,它就不会被输出;

2、代码示例

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.JoinFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;

import java.time.Duration;

/**
 * 注意:
 * <p>
 * 窗口中的水位线取的是两条流中的最小值;
 * 一个流中的元素如果没有与另一个流中的元素组合起来,它就不会被输出;
 */
public class _02_WindowSlidingEventJoin {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 测试时限制了分区数,生产中需要设置空闲数据源
        env.setParallelism(2);
        env.disableOperatorChaining();

        DataStreamSource<String> inputLeft = env.socketTextStream("localhost", 8888);

        // 事件时间需要设置水位线策略和时间戳
        SingleOutputStreamOperator<Tuple2<String, Long>> mapLeft = inputLeft.map(new MapFunction<String, Tuple2<String, Long>>() {
            @Override
            public Tuple2<String, Long> map(String input) throws Exception {
                String[] fields = input.split(",");
                return new Tuple2<>(fields[0], Long.parseLong(fields[1]));
            }
        });

        SingleOutputStreamOperator<Tuple2<String, Long>> watermarkLeft = mapLeft.assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple2<String, Long>>forBoundedOutOfOrderness(Duration.ofSeconds(0))
                .withTimestampAssigner(new SerializableTimestampAssigner<Tuple2<String, Long>>() {
                    @Override
                    public long extractTimestamp(Tuple2<String, Long> input, long l) {
                        return input.f1;
                    }
                }));

        DataStreamSource<String> inputRight = env.socketTextStream("localhost", 9999);

        // 事件时间需要设置水位线策略和时间戳
        SingleOutputStreamOperator<Tuple2<String, Long>> mapRight = inputRight.map(new MapFunction<String, Tuple2<String, Long>>() {
            @Override
            public Tuple2<String, Long> map(String input) throws Exception {
                String[] fields = input.split(",");
                return new Tuple2<>(fields[0], Long.parseLong(fields[1]));
            }
        });

        SingleOutputStreamOperator<Tuple2<String, Long>> watermarkRight = mapRight.assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple2<String, Long>>forBoundedOutOfOrderness(Duration.ofSeconds(0))
                .withTimestampAssigner(new SerializableTimestampAssigner<Tuple2<String, Long>>() {
                    @Override
                    public long extractTimestamp(Tuple2<String, Long> input, long l) {
                        return input.f1;
                    }
                }));

        watermarkLeft.join(watermarkRight)
                .where(e -> e.f0)
                .equalTo(e -> e.f0)
                .window(SlidingEventTimeWindows.of(Duration.ofSeconds(6), Duration.ofSeconds(3)))
                .apply(new JoinFunction<Tuple2<String, Long>, Tuple2<String, Long>, Tuple3<String, Long, Long>>() {
                    @Override
                    public Tuple3<String, Long, Long> join(Tuple2<String, Long> t1, Tuple2<String, Long> t2) throws Exception {
                        return new Tuple3<>(t1.f0, t1.f1, t2.f1);
                    }
                })
                .print();

        env.execute();
    }
}

3、测试用例

		  left-1
         
          a,1718089200000
          b,1718089200000
          c,1718089200000
         
          left-watermark=1718089199999
          window-watermark=no_watermark
         
          right-2
         
          a,1718089201000
          b,1718089201000
          c,1718089201000
         
          right-watermark=1718089200999
          window-watermark=1718089199999[两条流中最小的]
         
          left-3
         
          a,1718089204000
          b,1718089204000
          c,1718089204000
         
          left-watermark=1718089203999
          window-watermark=1718089200999
         
          right-4
         
          a,1718089205000
          b,1718089205000
          c,1718089205000
         
          right-watermark=1718089204999
          window-watermark=1718089203999
         
          res:[1718089197000~1718089203000]
         
          2> (a,1718089200000,1718089201000)
          1> (b,1718089200000,1718089201000)
          1> (c,1718089200000,1718089201000)
         
          left-5
         
          a,1718089209000
          b,1718089209000
          c,1718089209000
         
          left-watermark=1718089208999
          window-watermark=1718089204999
         
          right-6
         
          a,1718089209000
          b,1718089209000
          c,1718089209000
         
          right-watermark=1718089208999
          window-watermark=1718089208999
         
          res[1718089200000~1718089206000]
         
          2> (a,1718089200000,1718089201000)
          2> (a,1718089200000,1718089205000)
          2> (a,1718089204000,1718089201000)
          2> (a,1718089204000,1718089205000)
          1> (b,1718089200000,1718089201000)
          1> (b,1718089200000,1718089205000)
          1> (b,1718089204000,1718089201000)
          1> (b,1718089204000,1718089205000)
          1> (c,1718089200000,1718089201000)
          1> (c,1718089200000,1718089205000)
          1> (c,1718089204000,1718089201000)
          1> (c,1718089204000,1718089205000)
         
          res[1718089203000~1718089209000]
         
          2> (a,1718089204000,1718089205000)
          1> (b,1718089204000,1718089205000)
          1> (c,1718089204000,1718089205000)
  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Flink SQL中的JOIN操作可以和窗口一起使用,实现窗口上的JOIN计算,这可以在实时流处理中非常有用。 窗口是数据流处理中的一种重要概念,它可以将数据流按照时间或者数量等维度进行切分,然后对每个窗口内的数据进行计算。Flink SQL中支持多种类型的窗口,如滚动窗口滑动窗口、会话窗口等。 在使用Flink SQL进行JOIN操作时,可以将JOIN条件和窗口条件进行结合,以获取更加精细的数据切分和计算结果。例如,可以将两个数据流按照时间窗口进行JOIN操作,计算出在指定时间窗口内符合条件的数据。 具体来说,Flink SQL中的JOIN操作和窗口的结合有以下几个步骤: 1. 定义窗口:使用Flink SQL中的窗口函数,对数据流进行窗口切分,定义窗口大小和滑动步长等参数。 2. 分区数据:将数据流按照JOIN条件进行分区,将不同数据流中符合条件的数据分配到同一个计算节点上。 3. 缓存数据:将分区后的数据缓存到内存或者磁盘中,以供后续的JOIN计算使用。 4. JOIN计算:对缓存的数据按照JOIN条件进行JOIN计算,同时按照窗口条件进行分组计算,计算出符合条件的数据。 5. 输出结果:将JOIN计算的结果输出到指定的目标位置,以供后续的查询分析使用。 总的来说,Flink SQL中的JOIN操作和窗口的结合可以实现更加精细的数据切分和计算,可以在实时流处理中实现更加复杂的数据分析和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猫猫爱吃小鱼粮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值