两个数据流都源源不断地发生变化,而且数据流之间存在着某种联系,那么就可以用双流join将两个数据流关联起来。这里用异步IO可以吗?异步IO主要针对其中一个流固定不变(如geo字典库),并一个流在变化。用广播状态可以吗?广播状态只适用于数据量少和数据量变化不频繁地情况。
要实现两个数据流的关联,就需要创造两个数据流在同一时间能出现在同一个空间(同一subtask)的条件,而不是像两个流星一样转瞬即逝。首先我们可以按照要join的条件进行keyBy,让数据流进入到同一个分区;其次我们可以划窗口,让两个流数据放慢脚步,解决了数据流出现在同一时间段内的问题。此外还可以让两个流数据加上TTL都缓存一定的时间来实现。
滚动窗口join

滑动窗口join

会话窗口join

IntervalJoin

join(TumblingEventTimeWindows)
package cn._51doit.flink.day09;
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.api.java.tuple.Tuple5;
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.time.Duration;
/**
* 将两个数据流,进行join
*
* 如果让两个流能够join上,必须满足两个条件
* 1.数据分散在多台机器上,须将join条件相同的数据通过网络传输到同一台机器的同一个分区中(按照条件进行KeyBy)
* 2.让每个流中的数据都放慢脚步,等待对方(划分相同类型、长度一样的窗口)
*
*
*/
public class EventTimeTumblingWindowJoin {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//1000,c1,300
//4999,c1,300
//5000,c2,200
DataStreamSource<String> lines1 = env.socketTextStream("localhost", 8888);
//1200,c1,图书
//5001,c2,家具
DataStreamSource<String> lines2 = env.socketTextStream("localhost", 9999);
//期望返回的数据
//1000,c1,300,1200,图书
//按照EventTime进行join,窗口长度为5000秒,使用新的提取EventTime生成WaterMark的API
SingleOutputStreamOperator<String> lines1WithWaterMark = lines1.assignTimestampsAndWatermarks(WatermarkStrategy.<String>forBoundedOutOfOrderness(Duration.ofSeconds(0)).withTimestampAssigner(new SerializableTimestampAssigner<String>() {
@Override
public long extractTimestamp(String element, long recordTimestamp) {
return Long.parseLong(element.split(",")[0]);
}
}));
SingleOutputStreamOperator<Tuple3<Long, String, String>> tpStream1WithWaterMark = lines1WithWaterMark.map(new MapFunction<String, Tuple3<Long, String, String>>() {
@Override
public Tuple3<Long, String, String> map(String input) throws Exception {
String[] fields = input.split(",");
return Tuple3.of(Long.parseLong(fields[0

最低0.47元/天 解锁文章
1867

被折叠的 条评论
为什么被折叠?



