概述
Join:内连接
CoGroup:内连接,左连接,右连接
Interval Join:点对面
Join
- 1、Join 将有相同 Key 并且位于同一窗口中的两条流的元素进行关联。
- 2、Join 可以支持处理时间(processing time)和事件时间(event time)两种时间特征。
- 3、Join 通用用法如下:
- stream.join(otherStream)
- .where(<KeySelector>)
- .equalTo(<KeySelector>)
- .window(<WindowAssigner>)
- .apply(<JoinFunction>)
复制代码 滚动窗口
- package com.bigdata.day07;
- import org.apache.commons.lang3.time.DateUtils;
- 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.functions.KeySelector;
- import org.apache.flink.api.java.tuple.Tuple3;
- import org.apache.flink.streaming.api.datastream.DataStream;
- 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.TumblingEventTimeWindows;
- import org.apache.flink.streaming.api.windowing.time.Time;
- import java.text.ParseException;
- import java.time.Duration;
- import java.util.Date;
- /**
- * 内连接
- * 可以通过两个socket流,将数据合并为一个三元组,key,value1,value2
- */
- public class _01_双流join_join_内连接 {
- public static void main(String[] args) throws Exception {
- StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
- env.setParallelism(1);
-
- // 绿色的流
- DataStreamSource<String> source = env.socketTextStream("localhost", 7777);
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> greenSource = source.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
-
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- }));
-
- // 红色的流
- DataStreamSource<String> source2 = env.socketTextStream("localhost", 7778);
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> redSource = source2.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
-
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- }));
-
- // 双流join
- DataStream<Tuple3<String, Integer, Integer>> rsSource = greenSource.join(redSource).where(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- }).equalTo(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- // 滚动窗口
- }).window(TumblingEventTimeWindows.of(Time.seconds(5)))
- .apply(new JoinFunction<Tuple3<String, Integer, String>, Tuple3<String, Integer, String>, Tuple3<String, Integer, Integer>>() {
- @Override
- public Tuple3<String, Integer, Integer> join(Tuple3<String, Integer, String> first, Tuple3<String, Integer, String> second) throws Exception {
- return Tuple3.of(first.f0, first.f1, second.f1);
- }
- });
- redSource.print("红色的流:");
- greenSource.print("绿色的流:");
- rsSource.print("合并后的流:");
- env.execute();
- }
- }
复制代码 滑动窗口
- package com.bigdata.day07;
- import org.apache.flink.api.common.RuntimeExecutionMode;
- 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.Tuple3;
- import org.apache.flink.streaming.api.datastream.DataStream;
- 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 org.apache.flink.streaming.api.windowing.time.Time;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.time.Duration;
- import java.util.Date;
- /**
- * @基本功能: 演示join的滑动窗口
- * @program:FlinkDemo
- * @author: 闫哥
- * @create:2024-05-20 09:11:13
- **/
- public class Demo02Join {
- public static void main(String[] args) throws Exception {
- //1. env-准备环境
- StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
- env.setRuntimeMode(RuntimeExecutionMode.AUTOMATIC);
- // 将并行度设置为1,否则很难看到现象
- env.setParallelism(1);
- // 创建一个绿色的流
- DataStreamSource<String> greenSource = env.socketTextStream("localhost", 8899);
- // key,0,2021-03-26 12:09:00 将它变为三元组
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> greenDataStream = greenSource.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String value) throws Exception {
- String[] arr = value.split(",");
- return new Tuple3<>(arr[0], Integer.valueOf(arr[1]), arr[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- // 为什么这个地方的代码比之前要长,原因是以前获取的数据都是long类型,并且都是毫秒值
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> element, long recordTimestamp) {
- // 指定你的数据中哪一个是时间戳,并且时间戳必须是long类型,必须是毫秒为单位的。
- String time = element.f2; //2021-03-26 12:09:00
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- try {
- Date date = sdf.parse(time);
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- })
- );
- // 创建一个橘色的流
- DataStreamSource<String> orangeSource = env.socketTextStream("localhost", 9988);
- // key,0,2021-03-26 12:09:00 将它变为三元组
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> orangeDataStream = orangeSource.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String value) throws Exception {
- String[] arr = value.split(",");
- return new Tuple3<>(arr[0], Integer.valueOf(arr[1]), arr[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- // 为什么这个地方的代码比之前要长,原因是以前获取的数据都是long类型,并且都是毫秒值
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> element, long recordTimestamp) {
- // 指定你的数据中哪一个是时间戳,并且时间戳必须是long类型,必须是毫秒为单位的。
- String time = element.f2; //2021-03-26 12:09:00
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- try {
- Date date = sdf.parse(time);
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- })
- );
- //2. source-加载数据
- //3. transformation-数据处理转换
- DataStream<Tuple3<String, Integer, Integer>> resultStream = greenDataStream.join(orangeDataStream)
- .where(tuple3 -> tuple3.f0)
- .equalTo(tuple3 -> tuple3.f0)
- // 滑动窗口
- .window(SlidingEventTimeWindows.of(Time.seconds(5),Time.seconds(1)))
- .apply(new JoinFunction<Tuple3<String, Integer, String>, Tuple3<String, Integer, String>, Tuple3<String, Integer, Integer>>() {
- @Override
- public Tuple3<String, Integer, Integer> join(Tuple3<String, Integer, String> first, Tuple3<String, Integer, String> second) throws Exception {
- return Tuple3.of(first.f0, first.f1, second.f1);
- }
- });
- //4. sink-数据输出
- greenDataStream.print("绿色的流:");
- orangeDataStream.print("橘色的流:");
- resultStream.print("最终的结果:");
- //5. execute-执行
- env.execute();
- }
- }
复制代码 CoGroup
- 1、优势:可以实现内连接,左连接,右连接
- 2、劣势:内存压力大
- 3、和上面的写法区别:将join换成coGroup,apply中实现的具体方法有区别
- 4、流程
- stream.coGroup(otherStream)
- .where(<KeySelector>)
- .equalTo(<KeySelector>)
- .window(<WindowAssigner>)
- .apply(<CoGroupFunction>);
复制代码 内连接
- package com.bigdata.day07;
- import org.apache.commons.lang3.time.DateUtils;
- import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
- import org.apache.flink.api.common.eventtime.WatermarkStrategy;
- import org.apache.flink.api.common.functions.CoGroupFunction;
- import org.apache.flink.api.common.functions.JoinFunction;
- import org.apache.flink.api.common.functions.MapFunction;
- import org.apache.flink.api.java.functions.KeySelector;
- import org.apache.flink.api.java.tuple.Tuple3;
- import org.apache.flink.streaming.api.datastream.DataStream;
- 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.TumblingEventTimeWindows;
- import org.apache.flink.streaming.api.windowing.time.Time;
- import org.apache.flink.util.Collector;
- import java.text.ParseException;
- import java.time.Duration;
- import java.util.Date;
- /**
- * 内连接
- */
- public class _02_双流join_CoGroup_内连接 {
- public static void main(String[] args) throws Exception {
- StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
- env.setParallelism(1);
- // 绿色的流
- DataStreamSource<String> source = env.socketTextStream("localhost", 7777);
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> greenSource = source.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
-
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- }));
-
- // 红色的流
- DataStreamSource<String> source2 = env.socketTextStream("localhost", 7778);
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> redSource = source2.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- }));
-
-
- // 连接
- DataStream<Tuple3<String, String, String>> rsSource = greenSource.coGroup(redSource).where(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- }).equalTo(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- }).window(TumblingEventTimeWindows.of(Time.seconds(5))).apply(new CoGroupFunction<Tuple3<String, Integer, String>, Tuple3<String, Integer, String>, Tuple3<String, String, String>>() {
- @Override
- public void coGroup(Iterable<Tuple3<String, Integer, String>> first, Iterable<Tuple3<String, Integer, String>> second, Collector<Tuple3<String, String, String>> out) throws Exception {
- for (Tuple3<String, Integer, String> firesTuple3 : first) {
- for (Tuple3<String, Integer, String> secondTuple3 : second) {
- out.collect(Tuple3.of(firesTuple3.f0,"green"+firesTuple3.f1,"red"+secondTuple3.f1));
- }
- }
- }
- });
- redSource.print("红色的流:");
- greenSource.print("绿色的流:");
- rsSource.print("合并后的流:");
- env.execute();
- }
- }
复制代码 外连接
- package com.bigdata.day07;
- import org.apache.commons.lang3.time.DateUtils;
- import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
- import org.apache.flink.api.common.eventtime.WatermarkStrategy;
- import org.apache.flink.api.common.functions.CoGroupFunction;
- import org.apache.flink.api.common.functions.MapFunction;
- import org.apache.flink.api.java.functions.KeySelector;
- import org.apache.flink.api.java.tuple.Tuple3;
- import org.apache.flink.streaming.api.datastream.DataStream;
- 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.TumblingEventTimeWindows;
- import org.apache.flink.streaming.api.windowing.time.Time;
- import org.apache.flink.util.Collector;
- import java.text.ParseException;
- import java.time.Duration;
- import java.util.Date;
- /**
- * 外连接
- */
- public class _03_双流join_CoGroup_外连接 {
- public static void main(String[] args) throws Exception {
- StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
- env.setParallelism(1);
-
- // 绿色的流
- DataStreamSource<String> source = env.socketTextStream("localhost", 7777);
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> greenSource = source.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- }));
- // 红色的流
- DataStreamSource<String> source2 = env.socketTextStream("localhost", 7778);
- SingleOutputStreamOperator<Tuple3<String, Integer, String>> redSource = source2.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- }));
- DataStream<Tuple3<String, String, String>> rsSource = greenSource.coGroup(redSource).where(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- }).equalTo(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- }).window(TumblingEventTimeWindows.of(Time.seconds(5))).apply(new CoGroupFunction<Tuple3<String, Integer, String>, Tuple3<String, Integer, String>, Tuple3<String, String, String>>() {
- @Override
- public void coGroup(Iterable<Tuple3<String, Integer, String>> first, Iterable<Tuple3<String, Integer, String>> second, Collector<Tuple3<String, String, String>> out) throws Exception {
- // 内连接,左连接,右连接的区别只在这里面存在,两层循环
- for (Tuple3<String, Integer, String> firesTuple3 : first) {
- boolean isExist = false;
- for (Tuple3<String, Integer, String> secondTuple3 : second) {
- isExist = true;
- out.collect(Tuple3.of(firesTuple3.f0,"green"+firesTuple3.f1,"red"+secondTuple3.f1));
- }
- if (!isExist){
- out.collect(Tuple3.of(firesTuple3.f0,"green"+firesTuple3.f1,"red null"));
- }
- }
- }
- });
- redSource.print("红色的流:");
- greenSource.print("绿色的流:");
- rsSource.print("合并后的流:");
- env.execute();
- }
- }
复制代码 Interval Join
- 1、Join以及CoGroup 原因是 Join和CoGroup是窗口Join,必须给定窗口
- 2、Interval Join不需要给窗口。Interval Join 必须先分组才能使用。
- 3、先对数据源进行keyBy
- 4、 外流.intervalJoin(内流)
- .between(-2,2)
- .process
- between 左不包,右包
- 内部的流为下面的流(取单个值)
复制代码 代码实现
- package com.bigdata.day07;
- import org.apache.commons.lang3.time.DateUtils;
- import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
- import org.apache.flink.api.common.eventtime.WatermarkStrategy;
- import org.apache.flink.api.common.functions.CoGroupFunction;
- import org.apache.flink.api.common.functions.MapFunction;
- import org.apache.flink.api.java.functions.KeySelector;
- import org.apache.flink.api.java.tuple.Tuple3;
- import org.apache.flink.streaming.api.datastream.DataStream;
- import org.apache.flink.streaming.api.datastream.DataStreamSource;
- import org.apache.flink.streaming.api.datastream.KeyedStream;
- 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.assigners.TumblingEventTimeWindows;
- import org.apache.flink.streaming.api.windowing.time.Time;
- import org.apache.flink.util.Collector;
- import java.text.ParseException;
- import java.time.Duration;
- import java.util.Date;
- public class _04_双流join_Interval_Join {
- public static void main(String[] args) throws Exception {
- StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
- env.setParallelism(1);
-
- //绿色的流
- DataStreamSource<String> source = env.socketTextStream("localhost", 7777);
-
- KeyedStream<Tuple3<String, Integer, String>, String> greenSource = source.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- // 水印
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- // keyBy
- })).keyBy(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- });
- // 红色的流
- DataStreamSource<String> source2 = env.socketTextStream("localhost", 7778);
- KeyedStream<Tuple3<String, Integer, String>, String> redSource = source2.map(new MapFunction<String, Tuple3<String, Integer, String>>() {
- @Override
- public Tuple3<String, Integer, String> map(String line) throws Exception {
- String[] split = line.split(",");
- return Tuple3.of(split[0], Integer.valueOf(split[1]), split[2]);
- }
- // 水印
- }).assignTimestampsAndWatermarks(
- WatermarkStrategy.<Tuple3<String, Integer, String>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
- .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, String>>() {
- @Override
- public long extractTimestamp(Tuple3<String, Integer, String> tuple3, long recordTimestamp) {
- String timeStr = tuple3.f2;
- try {
- Date date = DateUtils.parseDate(timeStr, "yyyy-MM-dd hh-mm-ss");
- return date.getTime();
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- // 分组
- })).keyBy(new KeySelector<Tuple3<String, Integer, String>, String>() {
- @Override
- public String getKey(Tuple3<String, Integer, String> tuple3) throws Exception {
- return tuple3.f0;
- }
- });
-
- // 实现
- SingleOutputStreamOperator<String> rsSource = greenSource
- .intervalJoin(redSource)
- .between(Time.seconds(-2), Time.seconds(2))
- .process(new ProcessJoinFunction<Tuple3<String, Integer, String>, Tuple3<String, Integer, String>, String>() {
- @Override
- public void processElement(Tuple3<String, Integer, String> left, Tuple3<String, Integer, String> right, ProcessJoinFunction<Tuple3<String, Integer, String>, Tuple3<String, Integer, String>, String>.Context ctx, Collector<String> out) throws Exception {
- out.collect("left中的key:"+left.f0+",value="+left.f1+",time="+left.f2+",right中的key:"+right.f0+",value="+right.f1+",time="+right.f2);
- }
- });
- redSource.print("红色的流:");
- greenSource.print("绿色的流:");
- rsSource.print("合并后的流:");
- env.execute();
- /**
- * 红色的为下面的流
- * 范围:
- * 假如现在是10
- * 9 10 11 12
- */
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |