大数据-玩转数据-双流JOIN

一、双流JOIN

在Flink中, 支持两种方式的流的Join: Window Join和Interval Join

二、Window Join

窗口join会join具有相同的key并且处于同一个窗口中的两个流的元素.

注意:

1.所有的窗口join都是 inner join, 意味着a流中的元素如果在b流中没有对应的, 则a流中这个元素就不会处理(就是忽略掉了)

2.join成功后的元素的会以所在窗口的最大时间作为其时间戳. 例如窗口[5,10), 则元素会以9作为自己的时间戳。

Window join 仍然可分为 滚动窗口、滑动窗口Join、会话窗口Join

滚动窗口Join代码段示例

sql 复制代码
package com.lyh.flink12;
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.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

/**
 * @Author lizhenchao@atguigu.cn
 * @Date 2021/1/24 22:09
 */
public class Flink01_Join_Window_Tumbling {
    public static void main(String[] args) {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.createLocalEnvironmentWithWebUI(new Configuration());
        env.setParallelism(1);

        SingleOutputStreamOperator<WaterSensor> s1 = env
            .socketTextStream("hadoop100", 8888)  // 在socket终端只输入毫秒级别的时间戳
            .map(value -> {
                String[] datas = value.split(",");
                return new WaterSensor(datas[0], Long.valueOf(datas[1]), Integer.valueOf(datas[2]));

            })
            .assignTimestampsAndWatermarks(
                WatermarkStrategy
                    .<WaterSensor>forMonotonousTimestamps()
                    .withTimestampAssigner(new SerializableTimestampAssigner<WaterSensor>() {
                        @Override
                        public long extractTimestamp(WaterSensor element, long recordTimestamp) {
                            return element.getTs() * 1000;
                        }
                    })
            );

        SingleOutputStreamOperator<WaterSensor> s2 = env
            .socketTextStream("hadoop100", 9999)  // 在socket终端只输入毫秒级别的时间戳
            .map(value -> {
                String[] datas = value.split(",");
                return new WaterSensor(datas[0], Long.valueOf(datas[1]), Integer.valueOf(datas[2]));
            })
            .assignTimestampsAndWatermarks(
                WatermarkStrategy
                    .<WaterSensor>forMonotonousTimestamps()
                    .withTimestampAssigner(new SerializableTimestampAssigner<WaterSensor>() {
                        @Override
                        public long extractTimestamp(WaterSensor element, long recordTimestamp) {
                            return element.getTs() * 1000;
                        }
                    })
            );

        s1.join(s2)
            .where(WaterSensor::getId)
            .equalTo(WaterSensor::getId)
            .window(TumblingEventTimeWindows.of(Time.seconds(5))) // 必须使用窗口
            .apply(new JoinFunction<WaterSensor, WaterSensor, String>() {
                @Override
                public String join(WaterSensor first, WaterSensor second) throws Exception {
                    return "first: " + first + ", second: " + second;
                }
            })
            .print();

        try {
            env.execute();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果:

三、Interval Join

间隔流join(Interval Join), 是指使用一个流的数据按照key去join另外一条流的指定范围的数据.

如下图: 橙色的流去join绿色的流.范围是由橙色流的event-time + lower bound和event-time + upper bound来决定的.

orangeElem.ts + lowerBound <= greenElem.ts <= orangeElem.ts + upperBound

Interval Join只支持event-time

必须是keyBy之后的流才可以interval join

package com.lyh.flink12;

import com.lyh.bean.WaterSensor;

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;

import org.apache.flink.api.common.eventtime.WatermarkStrategy;

import org.apache.flink.configuration.Configuration;

import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;

import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import org.apache.flink.streaming.api.functions.co.ProcessJoinFunction;

import org.apache.flink.streaming.api.windowing.time.Time;

import org.apache.flink.table.planner.expressions.In;

import org.apache.flink.util.Collector;

sql 复制代码
import java.time.Duration;

public class  Sql_Join_Windows_Interval{
    public static void main(String[] args) {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.createLocalEnvironmentWithWebUI(new Configuration());
        env.setParallelism(2);
        SingleOutputStreamOperator<WaterSensor> s1 = env.socketTextStream("hadoop100", 8888)
                .map(value -> {
                    String[] data = value.split(",");
                    return new WaterSensor(
                            data[0],
                            Long.valueOf(data[1]),
                            Integer.valueOf(data[2]));

                }).assignTimestampsAndWatermarks(WatermarkStrategy.<WaterSensor>forBoundedOutOfOrderness(Duration.ofSeconds(2))
                        .withTimestampAssigner(new SerializableTimestampAssigner<WaterSensor>() {
                            @Override
                            public long extractTimestamp(WaterSensor element, long timestamp) {
                                return element.getTs();
                            }
                        }));

        SingleOutputStreamOperator<WaterSensor> s2 = env.socketTextStream("hadoop100", 9999)
                .map(value -> {
                    String[] data = value.split(",");
                    return new WaterSensor(
                            data[0],
                            Long.valueOf(data[1]),
                            Integer.valueOf(data[2]));

                }).assignTimestampsAndWatermarks(WatermarkStrategy.<WaterSensor>forBoundedOutOfOrderness(Duration.ofSeconds(2))
                        .withTimestampAssigner(new SerializableTimestampAssigner<WaterSensor>() {
                            @Override
                            public long extractTimestamp(WaterSensor element, long timestamp) {
                                return element.getTs();
                            }
                        }));

        s1.keyBy(WaterSensor::getId)
                .intervalJoin(s2.keyBy(WaterSensor::getId))
                .between(Time.seconds(-2),Time.seconds(3))
                .process(new ProcessJoinFunction<WaterSensor, WaterSensor, String>() {
                    @Override
                    public void processElement(WaterSensor left,
                                               WaterSensor right,
                                               Context ctx,
                                               Collector<String> out) throws Exception {
                        out.collect(left + "," + right);
                    }
                }).print();
        try{
            env.execute();
        } catch (Exception e)
        {e.printStackTrace();}

    }

}

运行结果:

相关推荐
宸津-代码粉碎机2 分钟前
Spring AI企业级Agent实战|多工具自动规划+并行调度落地,彻底解决复杂业务AI任务编排问题
java·大数据·人工智能·spring boot·python·spring
lixia0417mul25 分钟前
flink接入spring体系
java·spring·flink
TDengine (老段)9 分钟前
TDengine 数据修复与迁移 — VGroup 调度、S3 外挂与运维操作
大数据·运维·数据库·物联网·时序数据库·iot·tdengine
事变天下16 分钟前
国产ECMO破局者汉诺医疗闯关科创板:以“中国心”与“中国肺”托起生命希望
大数据·人工智能·microsoft
查拉图斯特拉面条21 分钟前
Git操作指南:克隆、提交、推送与避坑大全
大数据·git·elasticsearch
千桐科技31 分钟前
数字孪生泵站安全监测实战:从“事后抢修”到“预知大脑”
大数据·数字孪生·数据可视化·智慧水利
2601_950368911 小时前
稀土合金粉末采购指南:3步筛选靠谱镁钆供应商
大数据·运维·人工智能·python
兰令水1 小时前
【agent第3篇】agent上下文+面经
java·大数据·数据库
*neverGiveUp*1 小时前
PostgreSql常用SQL大全
数据库·sql·postgresql
段一凡-华北理工大学1 小时前
工业领域的Hadoop架构学习~系列文章15:机器学习与大数据融合 - 工业智能的算法引擎
大数据·人工智能·hadoop·机器学习·架构·工业智能体·高炉炼铁智能化